Пример #1
0
void main(int argc, char *argv[]) {

    std::string db_path;
    
    // if user doesn't provide filename, app will look in local profile
    if (argc > 1) {
      db_path = argv[1];
    } else {
      CHAR lpszPath[MAX_PATH];
      
      if (!SHGetSpecialFolderPath(NULL, lpszPath, 
            CSIDL_LOCAL_APPDATA, FALSE)) {
        
        exit_app("Unable to determine \"Local Settings\" folder");
      }
      // this path is probably different for older versions
      db_path = lpszPath;
      db_path += "\\Google\\Chrome\\User Data\\Default\\Login Data";
    
      // ensure file exists
      if (GetFileAttributes(db_path.c_str()) == INVALID_FILE_ATTRIBUTES) {
        printf("  Couldn't open \"%s\"", db_path.c_str());
      } else {
        list_entries(db_path);
      }
    }
    exit_app("");
}
Пример #2
0
int main(int argc, char *argv[])
{
    assert(sizeof(Header)     == 16);
    assert(sizeof(IndexEntry) == 24);

    parse_args(argc, argv);

    switch (arg_mode)
    {
    case LIST:
        open_archive(arg_archive);
        process_header();
        list_entries();
        close_archive();
        break;

    case EXTRACT:
        open_archive(arg_archive);
        process_header();
        extract_entries();
        close_archive();
        break;

    case CREATE:
        create_archive(arg_archive, (const char**)arg_files_begin,
                                    (const char**)arg_files_end, arg_com);
        break;
    }

    return 0;
}
Пример #3
0
static void uh_file_dirlist(struct client *cl, struct path_info *pi)
{
	struct dirent **files = NULL;
	int count = 0;

	uh_file_response_200(cl, NULL);
	ustream_printf(cl->us, "Content-Type: text/html\r\n\r\n");

	uh_chunk_printf(cl,
		"<html><head><title>Index of %s</title></head>"
		"<body><h1>Index of %s</h1><hr /><ol>",
		pi->name, pi->name);

	count = scandir(pi->phys, &files, NULL, dirent_cmp);
	if (count > 0) {
		strcpy(uh_buf, pi->phys);
		list_entries(cl, files, count, pi->name, uh_buf);
	}
	free(files);

	uh_chunk_printf(cl, "</ol><hr /></body></html>");
	request_done(cl);
}
Пример #4
0
Файл: add.c Проект: rdebath/sgt
void caltrap_add(int nargs, char **args, int nphysargs, struct entry *e)
{
    Date sd, ed;
    Time st, et;
    int i;
    char msg[512], *msgp, *p;
    struct entry ent;

    if (e->length == INVALID_DURATION)
	e->length = 0;

    if (e->period == INVALID_DURATION)
	e->period = 0;

    if (e->type == INVALID_TYPE)
	e->type = T_EVENT;

    if (nargs < 1 || nargs > 4)
	fatalerr_addargno();
    assert(nargs <= nphysargs);

    /*
     * We MUST see a date as the first argument.
     */
    sd = parse_date(args[0]);
    if (sd == INVALID_DATE)
	fatalerr_date(args[0]);

    i = 1;

    /*
     * Now we might see a time.
     */
    st = NO_TIME;
    if (nargs > i) {
	st = parse_time(args[i]);
	if (st != INVALID_TIME)
	    i++;
	else
	    st = NO_TIME;
    }

    /*
     * Now we expect to see a second date or time or both.
     */
    if (nargs > i) {
	ed = parse_date(args[i]);
	if (ed != INVALID_DATE)
	    i++;

	if (nargs > i) {
	    et = parse_time(args[i]);
	    if (et == INVALID_TIME)
		fatalerr_time(args[i]);
	    i++;
	    if (ed == INVALID_DATE) {
		/*
		 * If an end time was specified but no end date, we
		 * assume ed == sd.
		 */
		ed = sd;
	    }
	} else
	    et = 0;

	/*
	 * In this case, we normalise a missing start time to
	 * midnight.
	 */
	if (st == NO_TIME)
	    st = 0;
    } else {
	/*
	 * If there was no end time, choose one appropriately. An
	 * entry specifying just a date as input is taken to last
	 * exactly one day; an entry specifying just a start
	 * date+time is taken to be instantaneous.
	 */
	if (st == NO_TIME) {
	    st = 0;
	    ed = sd + 1;
	    et = 0;
	} else {
	    ed = sd;
	    et = st;
	}
    }

    if (i < nargs)
	fatalerr_extraarg(args[i]);

    msgp = e->description;

    if (isatty(fileno(stdin))) {
	char *dfmt, *tfmt;
	dfmt = format_date_full(sd);
	tfmt = format_time(st);
	printf("New entry will run from %s %s\n", dfmt, tfmt);
	sfree(dfmt);
	sfree(tfmt);
	if (e->period) {
	    Date td;
	    Time tt;
	    td = sd;
	    tt = st;
	    add_to_datetime(&td, &tt, e->length);
	    dfmt = format_date_full(td);
	    tfmt = format_time(tt);
	    printf("                     to %s %s\n", dfmt, tfmt);
	    sfree(dfmt);
	    sfree(tfmt);
	    dfmt = format_duration(e->period);
	    printf("        repeating every %s\n", dfmt);
	    sfree(dfmt);
	    td = sd;
	    tt = st;
	    add_to_datetime(&td, &tt, e->period);
	    dfmt = format_date_full(td);
	    tfmt = format_time(tt);
	    printf("so second occurrence is %s %s\n", dfmt, tfmt);
	    sfree(dfmt);
	    sfree(tfmt);
	    dfmt = format_date_full(ed);
	    tfmt = format_time(et);
	    printf("  and stop repeating on %s %s\n", dfmt, tfmt);
	    sfree(dfmt);
	    sfree(tfmt);
	} else {
	    dfmt = format_date_full(ed);
	    tfmt = format_time(et);
	    printf("                     to %s %s\n", dfmt, tfmt);
	    sfree(dfmt);
	    sfree(tfmt);
	}
	if (!msgp) {
	    printf("Existing entries in the week surrounding the start point:\n");
	    list_entries(sd - 3, 0, sd + 4, 0);
	    printf("Now enter message, on a single line,\n"
		   "or press ^D or ^C to cancel the operation.\n"
		   "> ");
	    fflush(stdout);
	}
    }

    if (!msgp) {
	if (!fgets(msg, sizeof(msg), stdin))
	    *msg = '\0';
	p = msg + strcspn(msg, "\r\n");
	if (!*p) {
	    printf("\nOperation cancelled.\n");
	    fflush(stdout);
	    return;
	}
	*p = '\0';
	msgp = msg;
    }

    ent.id = -1;		       /* cause a new id to be allocated */
    ent.sd = sd;
    ent.st = st;
    ent.ed = ed;
    ent.et = et;
    ent.length = e->length;
    ent.period = e->period;
    ent.type = e->type;
    ent.description = msgp;
    db_add_entry(&ent);
}
Пример #5
0
int main(void) {

	char line[MAX_LINE];
	entry *entryHead;       //head of entry list
	snapshot *snapHead;		//head of snapshot list
	entryHead = NULL;  
	snapHead = NULL;
	
	while (true) {
		printf("> ");

		if (fgets(line, MAX_LINE, stdin) == NULL) {
			printf("\n");
			command_bye(entryHead, snapHead);
			return 0;
		}
		
		//get command from the input line as well as a second parameter if it exists
		char *ptr = strtok(line, " ");
		char firstToken[MAX_COMMAND];    //stores a command
		strcpy(firstToken, ptr);
		ptr = strtok(NULL, " ");
		char secondToken[MAX_KEY];  	 //stores either a key or a second part of the command
		secondToken[0] = '\0';
		
		//get rid of a new line character if it exists in the last valid token entered
		char *newLine;
		if (ptr != NULL) {		
			strcpy(secondToken, ptr);
			newLine = strchr(secondToken, '\n');
		}
		else {
			newLine = strchr(firstToken, '\n');
		}
		if (newLine) {
			*newLine = 0;	
		}
		
		//identify the command and call the right function to execute the command entered
		if (strcasecmp(firstToken, "BYE") == 0) {
			command_bye(entryHead, snapHead);
			return 0;
		}
		else if (strcasecmp(firstToken, "HELP") == 0) {
			command_help();
		}
		else if (strcasecmp(firstToken, "LIST") == 0) {
			if (strcasecmp(secondToken, "ENTRIES") == 0) {
				list_entries(entryHead);	
			}
			else if (strcasecmp(secondToken, "KEYS") == 0) {
				list_keys(entryHead);
			}
			else if(strcasecmp(secondToken, "SNAPSHOTS") == 0) {
				list_snapshots(snapHead);
			}
			else {
				printf("unknown\n");	
			}
		}
		else if (strcasecmp(firstToken, "GET") == 0) {
			get(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "DEL") == 0) {
			entryHead = del(entryHead, secondToken);
		}
		else if (strcasecmp(firstToken, "PURGE") == 0) {
			entryHead = purge(secondToken, entryHead, snapHead);
		}
		else if (strcasecmp(firstToken, "SET") == 0) {
			if (ptr != NULL && secondToken[0] != '\0') {
				entryHead = set(ptr, secondToken, entryHead);
			}
			else {
				printf("invalid input\n");	
			}
		}
		else if (strcasecmp(firstToken, "PUSH") == 0 || strcasecmp(firstToken, "APPEND") == 0) {
			push_append(ptr, secondToken, entryHead, firstToken);
		}
		else if (strcasecmp(firstToken, "PICK") == 0) {
			ptr = strtok(NULL, " ");
			int index = atoi(ptr);
			pick(index, secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "PLUCK") == 0) {
			ptr = strtok(NULL, " ");
			int index = atoi(ptr);
			pluck(index, secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "POP") == 0) {
			pluck(1, secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "DROP") == 0) {
			snapHead = drop(snapHead, atoi(secondToken));
		}
		else if (strcasecmp(firstToken, "ROLLBACK") == 0) {
			entryHead = checkout(atoi(secondToken), entryHead, snapHead);
			snapHead = remove_snapshots(atoi(secondToken), snapHead);
		}
		else if (strcasecmp(firstToken, "CHECKOUT") == 0) {
			entryHead = checkout(atoi(secondToken), entryHead, snapHead);
		}
		else if (strcasecmp(firstToken, "SNAPSHOT") == 0) {
			snapHead = take_snapshot(entryHead, snapHead);
		}
		else if (strcasecmp(firstToken, "MIN") == 0) {
			min(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "MAX") == 0) {
			max(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "SUM") == 0) {
			sum(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "LEN") == 0) {
			len(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "REV") == 0) {
			reverse(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "UNIQ") == 0) {
			unique(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "SORT") == 0) {
			sort(secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "DIFF") == 0) {
			diff(ptr, secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "INTER") == 0) {
			inter(ptr, secondToken, entryHead);
		}
		else if (strcasecmp(firstToken, "UNION") == 0) {
			union_oper(ptr, secondToken, entryHead);
		}
		else {
			printf("unknown\n");	
		}
		
		printf("\n");
  	}

	return 0;
}
Пример #6
0
static void 
read_sref(FILE *fob, mxArray **data, double dbu_to_uu)
{
   mxArray *pstruct;
   mxArray *pprop = NULL;
   mxArray *pa;
   double *pd;
   tList xylist;
   uint16_t rtype, rlen;
   int nprop = 0;
   int mtotal = 0;
   int k, m, nle;
   element_t sref;
   const char *fields[] = {"internal", "xy", "prop"};
   xy_block vertex;


   /* initialize element */
   init_element(&sref, GDS_SREF);

   /* output data structure */
   pstruct = mxCreateStructMatrix(1,1, 3, fields);

   /* create a list for the XY data record(s) */
   if ( create_list(&xylist) == -1 )
      mexErrMsgTxt("gds_read_element (sref) :  could not create list for XY records.");

   /* read element properties */
   while (1) {
      
      if ( read_record_hdr(fob, &rtype, &rlen) )
	 mexErrMsgTxt("gds_read_element (sref) :  could not read record header.");

      if (rtype == ENDEL)
	 break;

      switch (rtype) {

         case XY:
	    m = rlen / (2*sizeof(int32_t));
	    vertex.mxy = m;
	    vertex.xy = read_xy2(fob, m, dbu_to_uu);
	    list_insert_object(xylist, &vertex, sizeof(xy_block), AFTER);
	    mtotal += m;
	    break;

         case SNAME:
	    if ( read_string(fob, sref.sname, rlen) )
	       mexErrMsgTxt("gds_read_element (sref) :  could not read structure name.");
	    break;

         case STRANS:
	    if ( read_word(fob, &sref.strans.flags) )
	       mexErrMsgTxt("gds_read_element (sref) :  could not read strans data.");
	    sref.has |= HAS_STRANS;
	    break;

         case MAG:
	    if ( read_real8(fob, &sref.strans.mag) )
	       mexErrMsgTxt("gds_read_element (sref) :  could not read magnification.");
	    sref.has |= HAS_MAG;
	    break;

         case ANGLE:
	    if ( read_real8(fob, &sref.strans.angle) )
	       mexErrMsgTxt("gds_read_element (sref) :  could not read angle.");
	    sref.has |= HAS_ANGLE;
	    break;

         case ELFLAGS:
	    sref.elflags = read_elflags(fob);
	    sref.has |= HAS_ELFLAGS;
	    break;

         case PLEX:
	    sref.plex = read_plex(fob);
	    sref.has |= HAS_PLEX;
	    break;

         case PROPATTR:
	    pprop = resize_property_structure(pprop, nprop+1);
	    mxSetFieldByNumber(pprop, nprop, 0, read_propattr(fob));
	    break;

         case PROPVALUE:
 	    mxSetFieldByNumber(pprop, nprop, 1, read_propvalue(fob,rlen));
	    nprop += 1;
	    break;

         default:
	    mexPrintf("Unknown record id: 0x%x\n", rtype);
	    mexErrMsgTxt("SREF :  found unknown element property.");
      }
   }

   /* catenate XY records */
   nle = list_entries(xylist);
   if ( !nle )
      mexErrMsgTxt("gds_read_element (sref) :  element has no XY record.");
   pa = mxCreateDoubleMatrix(mtotal,2, mxREAL);
   pd = mxGetData(pa);
   list_head(xylist);
   for (k=0; k<nle; k++) {
      get_current_object(xylist, &vertex, sizeof(xy_block));
      memcpy(pd, vertex.xy, 2*vertex.mxy*sizeof(double));
      pd += 2*vertex.mxy;
      mxFree(vertex.xy);
   }
   mxSetFieldByNumber(pstruct, 0, 1, pa);
   erase_list_entries(xylist);
   delete_list(&xylist);

   /* set prop field */
   if ( nprop ) {
      mxSetFieldByNumber(pstruct, 0, 2, pprop);
   }
   else {
      mxSetFieldByNumber(pstruct, 0, 2, empty_matrix());
   }

   /* store structure with element data */
   mxSetFieldByNumber(pstruct, 0, 0, copy_element_to_array(&sref));

   /* return data */
   *data = pstruct;
} 
Пример #7
0
static void 
read_path(FILE *fob, mxArray **data, double dbu_to_uu) 
{
   mxArray *pstruct;
   mxArray *pprop = NULL;
   mxArray *pc;
   tList xylist;
   uint16_t rtype, rlen;
   int nprop = 0;
   int nle, k;
   element_t path;
   const char *fields[] = {"internal", "xy", "prop"};


   /* initialize element */
   init_element(&path, GDS_PATH);

   /* output data structure */
   pstruct = mxCreateStructMatrix(1,1, 3, fields);

   /* create a list for the XY data record(s) */
   if ( create_list(&xylist) == -1 )
      mexErrMsgTxt("gds_read_element (path) :  could not create list for XY records.");

   /* read element properties */
   while (1) {
      
      if ( read_record_hdr(fob, &rtype, &rlen) )
	 mexErrMsgTxt("gds_read_element (path) :  could not read record header.");

      if (rtype == ENDEL)
	 break;

      switch (rtype) {

         case XY:
	    if ( list_insert(xylist, read_xy(fob, rlen, dbu_to_uu), AFTER) == -1)
	       mexErrMsgTxt("gds_read_element (path) :  list insertion failed.");
	    break;

         case LAYER:
	    path.layer = read_layer(fob);
	    break;

         case PATHTYPE:
	    path.ptype = read_type(fob);
	    path.has |= HAS_PTYPE;
	    break;

         case WIDTH:
	    path.width = dbu_to_uu * (double)read_width(fob);
	    path.has |= HAS_WIDTH;
	    break;

         case BGNEXTN:
	    path.bgnextn = dbu_to_uu * read_extn(fob);
	    path.has |= HAS_BGNEXTN;
	    break;

         case ENDEXTN:
	    path.endextn = dbu_to_uu * read_extn(fob);
	    path.has |= HAS_ENDEXTN;
	    break;

         case DATATYPE:
	    path.dtype = read_type(fob);
	    break;

         case ELFLAGS:
	    path.elflags = read_elflags(fob);
	    path.has |= HAS_ELFLAGS;
	    break;

         case PLEX:
	    path.plex = read_plex(fob);
	    path.has |= HAS_PLEX;
	    break;

         case PROPATTR:
	    pprop = resize_property_structure(pprop, nprop+1);
	    mxSetFieldByNumber(pprop, nprop, 0, read_propattr(fob));
	    break;

         case PROPVALUE:
 	    mxSetFieldByNumber(pprop, nprop, 1, read_propvalue(fob,rlen));
	    nprop += 1;
	    break;

         default:
	    mexPrintf("Unknown record id: 0x%x\n", rtype);
	    mexErrMsgTxt("PATH :  found unknown element property.");
      }
   }

   /* cell array with XY records */
   nle = list_entries(xylist);
   if ( !nle )
      mexErrMsgTxt("gds_read_element (path) :  element has no XY record.");
   pc = mxCreateCellMatrix(1, nle);
   list_head(xylist);
   for (k=0; k<nle; k++)
      mxSetCell(pc, k, (mxArray *)get_current_entry(xylist, NULL));
   mxSetFieldByNumber(pstruct, 0, 1, pc);

   /* set prop field */
   if ( nprop ) {
      mxSetFieldByNumber(pstruct, 0, 2, pprop);
   }
   else {
      mxSetFieldByNumber(pstruct, 0, 2, empty_matrix());
   }

   /* store structure with element data */
   mxSetFieldByNumber(pstruct, 0, 0, copy_element_to_array(&path));

   /* return data */
   *data = pstruct;
}
int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
		bool restore)
{
	struct iptables_command_state cs;
	int verbose = 0;
	const char *chain = NULL;
	const char *policy = NULL, *newname = NULL;
	unsigned int rulenum = 0, command = 0;
	int ret = 1;
	struct xtables_match *m;
	struct xtables_rule_match *matchp;
	struct xtables_target *t;
	struct xtables_args args = {
		.family	= h->family,
	};

	memset(&cs, 0, sizeof(cs));
	cs.jumpto = "";
	cs.argv = argv;

	/* re-set optind to 0 in case do_command4 gets called
	 * a second time */
	optind = 0;

	/* clear mflags in case do_command4 gets called a second time
	 * (we clear the global list of all matches for security)*/
	for (m = xtables_matches; m; m = m->next)
		m->mflags = 0;

	for (t = xtables_targets; t; t = t->next) {
		t->tflags = 0;
		t->used = 0;
	}

	/* Suppress error messages: we may add new options if we
	   demand-load a protocol. */
	opterr = 0;

	h->ops = nft_family_ops_lookup(h->family);
	if (h->ops == NULL)
		xtables_error(PARAMETER_PROBLEM, "Unknown family");

	opts = xt_params->orig_opts;
	while ((cs.c = getopt_long(argc, argv,
	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:46",
					   opts, NULL)) != -1) {
		switch (cs.c) {
			/*
			 * Command selection
			 */
		case 'A':
			add_command(&command, CMD_APPEND, CMD_NONE,
				    cs.invert);
			chain = optarg;
			break;

		case 'C':
			add_command(&command, CMD_CHECK, CMD_NONE,
				    cs.invert);
			chain = optarg;
			break;

		case 'D':
			add_command(&command, CMD_DELETE, CMD_NONE,
				    cs.invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!') {
				rulenum = parse_rulenumber(argv[optind++]);
				command = CMD_DELETE_NUM;
			}
			break;

		case 'R':
			add_command(&command, CMD_REPLACE, CMD_NONE,
				    cs.invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				rulenum = parse_rulenumber(argv[optind++]);
			else
				xtables_error(PARAMETER_PROBLEM,
					   "-%c requires a rule number",
					   cmd2char(CMD_REPLACE));
			break;

		case 'I':
			add_command(&command, CMD_INSERT, CMD_NONE,
				    cs.invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				rulenum = parse_rulenumber(argv[optind++]);
			else rulenum = 1;
			break;

		case 'L':
			add_command(&command, CMD_LIST,
				    CMD_ZERO | CMD_ZERO_NUM, cs.invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				 && argv[optind][0] != '!')
				chain = argv[optind++];
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				rulenum = parse_rulenumber(argv[optind++]);
			break;

		case 'S':
			add_command(&command, CMD_LIST_RULES,
				    CMD_ZERO|CMD_ZERO_NUM, cs.invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				 && argv[optind][0] != '!')
				chain = argv[optind++];
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				rulenum = parse_rulenumber(argv[optind++]);
			break;

		case 'F':
			add_command(&command, CMD_FLUSH, CMD_NONE,
				    cs.invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				 && argv[optind][0] != '!')
				chain = argv[optind++];
			break;

		case 'Z':
			add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES,
				    cs.invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				&& argv[optind][0] != '!')
				chain = argv[optind++];
			if (optind < argc && argv[optind][0] != '-'
				&& argv[optind][0] != '!') {
				rulenum = parse_rulenumber(argv[optind++]);
				command = CMD_ZERO_NUM;
			}
			break;

		case 'N':
			if (optarg && (*optarg == '-' || *optarg == '!'))
				xtables_error(PARAMETER_PROBLEM,
					   "chain name not allowed to start "
					   "with `%c'\n", *optarg);
			if (xtables_find_target(optarg, XTF_TRY_LOAD))
				xtables_error(PARAMETER_PROBLEM,
					   "chain name may not clash "
					   "with target name\n");
			add_command(&command, CMD_NEW_CHAIN, CMD_NONE,
				    cs.invert);
			chain = optarg;
			break;

		case 'X':
			add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
				    cs.invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				 && argv[optind][0] != '!')
				chain = argv[optind++];
			break;

		case 'E':
			add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
				    cs.invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				newname = argv[optind++];
			else
				xtables_error(PARAMETER_PROBLEM,
					   "-%c requires old-chain-name and "
					   "new-chain-name",
					    cmd2char(CMD_RENAME_CHAIN));
			break;

		case 'P':
			add_command(&command, CMD_SET_POLICY, CMD_NONE,
				    cs.invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				policy = argv[optind++];
			else
				xtables_error(PARAMETER_PROBLEM,
					   "-%c requires a chain and a policy",
					   cmd2char(CMD_SET_POLICY));
			break;

		case 'h':
			if (!optarg)
				optarg = argv[optind];

			/* iptables -p icmp -h */
			if (!cs.matches && cs.protocol)
				xtables_find_match(cs.protocol,
					XTF_TRY_LOAD, &cs.matches);

			exit_printhelp(cs.matches);

			/*
			 * Option selection
			 */
		case 'p':
			set_option(&cs.options, OPT_PROTOCOL, &args.invflags,
				   cs.invert);

			/* Canonicalize into lower case */
			for (cs.protocol = optarg; *cs.protocol; cs.protocol++)
				*cs.protocol = tolower(*cs.protocol);

			cs.protocol = optarg;
			args.proto = xtables_parse_protocol(cs.protocol);

			if (args.proto == 0 && (args.invflags & XT_INV_PROTO))
				xtables_error(PARAMETER_PROBLEM,
					   "rule would never match protocol");

			/* This needs to happen here to parse extensions */
			h->ops->proto_parse(&cs, &args);
			break;

		case 's':
			set_option(&cs.options, OPT_SOURCE, &args.invflags,
				   cs.invert);
			args.shostnetworkmask = optarg;
			break;

		case 'd':
			set_option(&cs.options, OPT_DESTINATION,
				   &args.invflags, cs.invert);
			args.dhostnetworkmask = optarg;
			break;

#ifdef IPT_F_GOTO
		case 'g':
			set_option(&cs.options, OPT_JUMP, &args.invflags,
				   cs.invert);
			args.goto_set = true;
			cs.jumpto = parse_target(optarg);
			break;
#endif

		case 'j':
			command_jump(&cs);
			break;


		case 'i':
			if (*optarg == '\0')
				xtables_error(PARAMETER_PROBLEM,
					"Empty interface is likely to be "
					"undesired");
			set_option(&cs.options, OPT_VIANAMEIN, &args.invflags,
				   cs.invert);
			xtables_parse_interface(optarg,
						args.iniface,
						args.iniface_mask);
			break;

		case 'o':
			if (*optarg == '\0')
				xtables_error(PARAMETER_PROBLEM,
					"Empty interface is likely to be "
					"undesired");
			set_option(&cs.options, OPT_VIANAMEOUT, &args.invflags,
				   cs.invert);
			xtables_parse_interface(optarg,
						args.outiface,
						args.outiface_mask);
			break;

		case 'f':
			if (args.family == AF_INET6) {
				xtables_error(PARAMETER_PROBLEM,
					"`-f' is not supported in IPv6, "
					"use -m frag instead");
			}
			set_option(&cs.options, OPT_FRAGMENT, &args.invflags,
				   cs.invert);
			args.flags |= IPT_F_FRAG;
			break;

		case 'v':
			if (!verbose)
				set_option(&cs.options, OPT_VERBOSE,
					   &args.invflags, cs.invert);
			verbose++;
			break;

		case 'm':
			command_match(&cs);
			break;

		case 'n':
			set_option(&cs.options, OPT_NUMERIC, &args.invflags,
				   cs.invert);
			break;

		case 't':
			if (cs.invert)
				xtables_error(PARAMETER_PROBLEM,
					   "unexpected ! flag before --table");
			*table = optarg;
			break;

		case 'x':
			set_option(&cs.options, OPT_EXPANDED, &args.invflags,
				   cs.invert);
			break;

		case 'V':
			if (cs.invert)
				printf("Not %s ;-)\n", prog_vers);
			else
				printf("%s v%s\n",
				       prog_name, prog_vers);
			exit(0);

		case 'w':
			if (restore) {
				xtables_error(PARAMETER_PROBLEM,
					      "You cannot use `-w' from "
					      "iptables-restore");
			}
			break;

		case '0':
			set_option(&cs.options, OPT_LINENUMBERS,
				   &args.invflags, cs.invert);
			break;

		case 'M':
			xtables_modprobe_program = optarg;
			break;

		case 'c':

			set_option(&cs.options, OPT_COUNTERS, &args.invflags,
				   cs.invert);
			args.pcnt = optarg;
			args.bcnt = strchr(args.pcnt + 1, ',');
			if (args.bcnt)
			    args.bcnt++;
			if (!args.bcnt && optind < argc &&
			    argv[optind][0] != '-' &&
			    argv[optind][0] != '!')
				args.bcnt = argv[optind++];
			if (!args.bcnt)
				xtables_error(PARAMETER_PROBLEM,
					"-%c requires packet and byte counter",
					opt2char(OPT_COUNTERS));

			if (sscanf(args.pcnt, "%llu", &args.pcnt_cnt) != 1)
				xtables_error(PARAMETER_PROBLEM,
					"-%c packet counter not numeric",
					opt2char(OPT_COUNTERS));

			if (sscanf(args.bcnt, "%llu", &args.bcnt_cnt) != 1)
				xtables_error(PARAMETER_PROBLEM,
					"-%c byte counter not numeric",
					opt2char(OPT_COUNTERS));
			break;

		case '4':
			if (args.family != AF_INET)
				exit_tryhelp(2);

			h->ops = nft_family_ops_lookup(args.family);
			break;

		case '6':
			args.family = AF_INET6;
			xtables_set_nfproto(AF_INET6);

			h->ops = nft_family_ops_lookup(args.family);
			if (h->ops == NULL)
				xtables_error(PARAMETER_PROBLEM,
					      "Unknown family");
			break;

		case 1: /* non option */
			if (optarg[0] == '!' && optarg[1] == '\0') {
				if (cs.invert)
					xtables_error(PARAMETER_PROBLEM,
						   "multiple consecutive ! not"
						   " allowed");
				cs.invert = TRUE;
				optarg[0] = '\0';
				continue;
			}
			fprintf(stderr, "Bad argument `%s'\n", optarg);
			exit_tryhelp(2);

		default:
			if (command_default(&cs, &xtables_globals) == 1)
				/* cf. ip6tables.c */
				continue;
			break;
		}
		cs.invert = FALSE;
	}

	if (strcmp(*table, "nat") == 0 &&
	    ((policy != NULL && strcmp(policy, "DROP") == 0) ||
	    (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0)))
		xtables_error(PARAMETER_PROBLEM,
			"\nThe \"nat\" table is not intended for filtering, "
			"the use of DROP is therefore inhibited.\n\n");

	for (matchp = cs.matches; matchp; matchp = matchp->next)
		xtables_option_mfcall(matchp->match);
	if (cs.target != NULL)
		xtables_option_tfcall(cs.target);

	/* Fix me: must put inverse options checking here --MN */

	if (optind < argc)
		xtables_error(PARAMETER_PROBLEM,
			   "unknown arguments found on commandline");
	if (!command)
		xtables_error(PARAMETER_PROBLEM, "no command specified");
	if (cs.invert)
		xtables_error(PARAMETER_PROBLEM,
			   "nothing appropriate following !");

	/* Set only if required, needed by xtables-restore */
	if (h->family == AF_UNSPEC)
		h->family = args.family;

	h->ops->post_parse(command, &cs, &args);

	if (command == CMD_REPLACE &&
	    (args.s.naddrs != 1 || args.d.naddrs != 1))
		xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
			   "specify a unique address");

	generic_opt_check(command, cs.options);

	if (chain != NULL && strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
		xtables_error(PARAMETER_PROBLEM,
			   "chain name `%s' too long (must be under %u chars)",
			   chain, XT_EXTENSION_MAXNAMELEN);

	if (command == CMD_APPEND
	    || command == CMD_DELETE
	    || command == CMD_CHECK
	    || command == CMD_INSERT
	    || command == CMD_REPLACE) {
		if (strcmp(chain, "PREROUTING") == 0
		    || strcmp(chain, "INPUT") == 0) {
			/* -o not valid with incoming packets. */
			if (cs.options & OPT_VIANAMEOUT)
				xtables_error(PARAMETER_PROBLEM,
					   "Can't use -%c with %s\n",
					   opt2char(OPT_VIANAMEOUT),
					   chain);
		}

		if (strcmp(chain, "POSTROUTING") == 0
		    || strcmp(chain, "OUTPUT") == 0) {
			/* -i not valid with outgoing packets */
			if (cs.options & OPT_VIANAMEIN)
				xtables_error(PARAMETER_PROBLEM,
					   "Can't use -%c with %s\n",
					   opt2char(OPT_VIANAMEIN),
					   chain);
		}

		/*
		 * Contrary to what iptables does, we assume that any jumpto
		 * is a custom chain jumps (if no target is found). Later on,
		 * nf_table will spot the error if the chain does not exists.
		 */
	}

	switch (command) {
	case CMD_APPEND:
		ret = add_entry(chain, *table, &cs, 0, h->family,
				args.s, args.d, cs.options&OPT_VERBOSE,
				h, true);
		break;
	case CMD_DELETE:
		ret = delete_entry(chain, *table, &cs, h->family,
				   args.s, args.d, cs.options&OPT_VERBOSE, h);
		break;
	case CMD_DELETE_NUM:
		ret = nft_rule_delete_num(h, chain, *table, rulenum - 1, verbose);
		break;
	case CMD_CHECK:
		ret = check_entry(chain, *table, &cs, h->family,
				   args.s, args.d, cs.options&OPT_VERBOSE, h);
		break;
	case CMD_REPLACE:
		ret = replace_entry(chain, *table, &cs, rulenum - 1,
				    h->family, args.s, args.d,
				    cs.options&OPT_VERBOSE, h);
		break;
	case CMD_INSERT:
		ret = add_entry(chain, *table, &cs, rulenum - 1, h->family,
				args.s, args.d, cs.options&OPT_VERBOSE, h,
				false);
		break;
	case CMD_FLUSH:
		ret = nft_rule_flush(h, chain, *table);
		break;
	case CMD_ZERO:
		ret = nft_chain_zero_counters(h, chain, *table);
		break;
	case CMD_ZERO_NUM:
		ret = nft_rule_zero_counters(h, chain, *table, rulenum - 1);
		break;
	case CMD_LIST:
	case CMD_LIST|CMD_ZERO:
	case CMD_LIST|CMD_ZERO_NUM:
		ret = list_entries(h, chain, *table,
				   rulenum,
				   cs.options&OPT_VERBOSE,
				   cs.options&OPT_NUMERIC,
				   cs.options&OPT_EXPANDED,
				   cs.options&OPT_LINENUMBERS);
		if (ret && (command & CMD_ZERO))
			ret = nft_chain_zero_counters(h, chain, *table);
		if (ret && (command & CMD_ZERO_NUM))
			ret = nft_rule_zero_counters(h, chain, *table,
						     rulenum - 1);
		break;
	case CMD_LIST_RULES:
	case CMD_LIST_RULES|CMD_ZERO:
	case CMD_LIST_RULES|CMD_ZERO_NUM:
		ret = list_rules(h, chain, *table, rulenum, cs.options&OPT_VERBOSE);
		if (ret && (command & CMD_ZERO))
			ret = nft_chain_zero_counters(h, chain, *table);
		if (ret && (command & CMD_ZERO_NUM))
			ret = nft_rule_zero_counters(h, chain, *table,
						     rulenum - 1);
		break;
	case CMD_NEW_CHAIN:
		ret = nft_chain_user_add(h, chain, *table);
		break;
	case CMD_DELETE_CHAIN:
		ret = nft_chain_user_del(h, chain, *table);
		break;
	case CMD_RENAME_CHAIN:
		ret = nft_chain_user_rename(h, chain, *table, newname);
		break;
	case CMD_SET_POLICY:
		ret = nft_chain_set(h, *table, chain, policy, NULL);
		if (ret < 0)
			xtables_error(PARAMETER_PROBLEM, "Wrong policy `%s'\n",
				      policy);
		break;
	default:
		/* We should never reach this... */
		exit_tryhelp(2);
	}

/*	if (verbose > 1)
		dump_entries(*handle); */

	xtables_rule_matches_free(&cs.matches);

	if (h->family == AF_INET) {
		free(args.s.addr.v4);
		free(args.s.mask.v4);
		free(args.d.addr.v4);
		free(args.d.mask.v4);
	} else if (h->family == AF_INET6) {
		free(args.s.addr.v6);
		free(args.s.mask.v6);
		free(args.d.addr.v6);
		free(args.d.mask.v6);
	}
	xtables_free_opts(1);

	return ret;
}
Пример #9
0
int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
{
	struct arptables_command_state cs;
	int invert = 0;
	unsigned int nsaddrs = 0, ndaddrs = 0;
	struct in_addr *saddrs = NULL, *daddrs = NULL;

	int c, verbose = 0;
	const char *chain = NULL;
	const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
	const char *policy = NULL, *newname = NULL;
	unsigned int rulenum = 0, options = 0, command = 0;
	const char *pcnt = NULL, *bcnt = NULL;
	int ret = 1;
	struct xtables_target *t;

	memset(&cs, 0, sizeof(cs));
	cs.jumpto = "";

	opts = original_opts;
	global_option_offset = 0;

	xtables_globals.orig_opts = original_opts;

	/* re-set optind to 0 in case do_command gets called
	 * a second time */
	optind = 0;

	for (t = xtables_targets; t; t = t->next) {
		t->tflags = 0;
		t->used = 0;
	}

	/* Suppress error messages: we may add new options if we
	    demand-load a protocol. */
	opterr = 0;

	while ((c = getopt_long(argc, argv,
	   "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:l:i:vnt:m:c:",
					   opts, NULL)) != -1) {
		switch (c) {
			/*
			 * Command selection
			 */
		case 'A':
			add_command(&command, CMD_APPEND, CMD_NONE,
				    invert);
			chain = optarg;
			break;

		case 'D':
			add_command(&command, CMD_DELETE, CMD_NONE,
				    invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!') {
				rulenum = parse_rulenumber(argv[optind++]);
				command = CMD_DELETE_NUM;
			}
			break;

		case 'R':
			add_command(&command, CMD_REPLACE, CMD_NONE,
				    invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				rulenum = parse_rulenumber(argv[optind++]);
			else
				xtables_error(PARAMETER_PROBLEM,
					      "-%c requires a rule number",
					      cmd2char(CMD_REPLACE));
			break;

		case 'I':
			add_command(&command, CMD_INSERT, CMD_NONE,
				    invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				rulenum = parse_rulenumber(argv[optind++]);
			else rulenum = 1;
			break;

		case 'L':
			add_command(&command, CMD_LIST, CMD_ZERO,
				    invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				 && argv[optind][0] != '!')
				chain = argv[optind++];
			break;

		case 'F':
			add_command(&command, CMD_FLUSH, CMD_NONE,
				    invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				 && argv[optind][0] != '!')
				chain = argv[optind++];
			break;

		case 'Z':
			add_command(&command, CMD_ZERO, CMD_LIST,
				    invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				&& argv[optind][0] != '!')
				chain = argv[optind++];
			break;

		case 'N':
			if (optarg && *optarg == '-')
				xtables_error(PARAMETER_PROBLEM,
					      "chain name not allowed to start "
					      "with `-'\n");
			if (xtables_find_target(optarg, XTF_TRY_LOAD))
				xtables_error(PARAMETER_PROBLEM,
						"chain name may not clash "
						"with target name\n");
			add_command(&command, CMD_NEW_CHAIN, CMD_NONE,
				    invert);
			chain = optarg;
			break;

		case 'X':
			add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
				    invert);
			if (optarg) chain = optarg;
			else if (optind < argc && argv[optind][0] != '-'
				 && argv[optind][0] != '!')
				chain = argv[optind++];
			break;

		case 'E':
			add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
				    invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				newname = argv[optind++];
			else
				xtables_error(PARAMETER_PROBLEM,
					      "-%c requires old-chain-name and "
					      "new-chain-name",
					      cmd2char(CMD_RENAME_CHAIN));
			break;

		case 'P':
			add_command(&command, CMD_SET_POLICY, CMD_NONE,
				    invert);
			chain = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				policy = argv[optind++];
			else
				xtables_error(PARAMETER_PROBLEM,
					      "-%c requires a chain and a policy",
					      cmd2char(CMD_SET_POLICY));
			break;

		case 'h':
			if (!optarg)
				optarg = argv[optind];

			exit_printhelp();
			break;
		case 's':
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_S_IP, &cs.fw.arp.invflags,
				   invert);
			shostnetworkmask = argv[optind-1];
			break;

		case 'd':
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_D_IP, &cs.fw.arp.invflags,
				   invert);
			dhostnetworkmask = argv[optind-1];
			break;

		case 2:/* src-mac */
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_S_MAC, &cs.fw.arp.invflags,
				   invert);
			if (getmac_and_mask(argv[optind - 1],
			    cs.fw.arp.src_devaddr.addr, cs.fw.arp.src_devaddr.mask))
				xtables_error(PARAMETER_PROBLEM, "Problem with specified "
						"source mac");
			break;

		case 3:/* dst-mac */
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_D_MAC, &cs.fw.arp.invflags,
				   invert);

			if (getmac_and_mask(argv[optind - 1],
			    cs.fw.arp.tgt_devaddr.addr, cs.fw.arp.tgt_devaddr.mask))
				xtables_error(PARAMETER_PROBLEM, "Problem with specified "
						"destination mac");
			break;

		case 'l':/* hardware length */
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_H_LENGTH, &cs.fw.arp.invflags,
				   invert);
			getlength_and_mask(argv[optind - 1], &cs.fw.arp.arhln,
					   &cs.fw.arp.arhln_mask);

			if (cs.fw.arp.arhln != 6) {
				xtables_error(PARAMETER_PROBLEM,
					      "Only harware address length of"
					      " 6 is supported currently.");
			}

			break;

		case 8:/* protocol length */
			xtables_error(PARAMETER_PROBLEM, "not supported");
/*
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_P_LENGTH, &cs.fw.arp.invflags,
				   invert);

			getlength_and_mask(argv[optind - 1], &cs.fw.arp.arpln,
					   &cs.fw.arp.arpln_mask);
			break;
*/

		case 4:/* opcode */
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_OPCODE, &cs.fw.arp.invflags,
				   invert);
			if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arpop,
					   &cs.fw.arp.arpop_mask, 10)) {
				int i;

				for (i = 0; i < NUMOPCODES; i++)
					if (!strcasecmp(opcodes[i], optarg))
						break;
				if (i == NUMOPCODES)
					xtables_error(PARAMETER_PROBLEM, "Problem with specified opcode");
				cs.fw.arp.arpop = htons(i+1);
			}
			break;

		case 5:/* h-type */
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_H_TYPE, &cs.fw.arp.invflags,
				   invert);
			if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arhrd,
					   &cs.fw.arp.arhrd_mask, 16)) {
				if (strcasecmp(argv[optind-1], "Ethernet"))
					xtables_error(PARAMETER_PROBLEM, "Problem with specified hardware type");
				cs.fw.arp.arhrd = htons(1);
			}
			break;

		case 6:/* proto-type */
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_P_TYPE, &cs.fw.arp.invflags,
				   invert);
			if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arpro,
					   &cs.fw.arp.arpro_mask, 0)) {
				if (strcasecmp(argv[optind-1], "ipv4"))
					xtables_error(PARAMETER_PROBLEM, "Problem with specified protocol type");
				cs.fw.arp.arpro = htons(0x800);
			}
			break;

		case 'j':
			set_option(&options, OPT_JUMP, &cs.fw.arp.invflags,
				   invert);
			cs.jumpto = parse_target(optarg);
			cs.target = command_jump(&cs.fw, cs.jumpto);
			break;

		case 'i':
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_VIANAMEIN, &cs.fw.arp.invflags,
				   invert);
			parse_interface(argv[optind-1],
					cs.fw.arp.iniface,
					cs.fw.arp.iniface_mask);
/*			cs.fw.nfcache |= NFC_IP_IF_IN; */
			break;

		case 'o':
			check_inverse(optarg, &invert, &optind, argc);
			set_option(&options, OPT_VIANAMEOUT, &cs.fw.arp.invflags,
				   invert);
			parse_interface(argv[optind-1],
					cs.fw.arp.outiface,
					cs.fw.arp.outiface_mask);
			/* cs.fw.nfcache |= NFC_IP_IF_OUT; */
			break;

		case 'v':
			if (!verbose)
				set_option(&options, OPT_VERBOSE,
					   &cs.fw.arp.invflags, invert);
			verbose++;
			break;

		case 'm': /*{
			size_t size;

			if (invert)
				exit_error(PARAMETER_PROBLEM,
					   "unexpected ! flag before --match");

			m = find_match(optarg, LOAD_MUST_SUCCEED);
			size = ARPT_ALIGN(sizeof(struct arpt_entry_match))
					 + m->size;
			m->m = fw_calloc(1, size);
			m->m->u.match_size = size;
			strcpy(m->m->u.user.name, m->name);
			m->init(m->m, &fw.nfcache);
			opts = merge_options(opts, m->extra_opts, &m->option_offset);
		}*/
		break;

		case 'n':
			set_option(&options, OPT_NUMERIC, &cs.fw.arp.invflags,
				   invert);
			break;

		case 't':
			if (invert)
				xtables_error(PARAMETER_PROBLEM,
					      "unexpected ! flag before --table");
			*table = argv[optind-1];
			break;

		case 'V':
			if (invert)
				printf("Not %s ;-)\n", program_version);
			else
				printf("%s v%s\n",
				       program_name, program_version);
			exit(0);

		case '0':
			set_option(&options, OPT_LINENUMBERS, &cs.fw.arp.invflags,
				   invert);
			break;

		case 'M':
			//modprobe = optarg;
			break;

		case 'c':

			set_option(&options, OPT_COUNTERS, &cs.fw.arp.invflags,
				   invert);
			pcnt = optarg;
			if (optind < argc && argv[optind][0] != '-'
			    && argv[optind][0] != '!')
				bcnt = argv[optind++];
			else
				xtables_error(PARAMETER_PROBLEM,
					      "-%c requires packet and byte counter",
					      opt2char(OPT_COUNTERS));

			if (sscanf(pcnt, "%llu", &cs.fw.counters.pcnt) != 1)
			xtables_error(PARAMETER_PROBLEM,
				"-%c packet counter not numeric",
				opt2char(OPT_COUNTERS));

			if (sscanf(bcnt, "%llu", &cs.fw.counters.bcnt) != 1)
				xtables_error(PARAMETER_PROBLEM,
					      "-%c byte counter not numeric",
					      opt2char(OPT_COUNTERS));

			break;


		case 1: /* non option */
			if (optarg[0] == '!' && optarg[1] == '\0') {
				if (invert)
					xtables_error(PARAMETER_PROBLEM,
						      "multiple consecutive ! not"
						      " allowed");
				invert = TRUE;
				optarg[0] = '\0';
				continue;
			}
			printf("Bad argument `%s'\n", optarg);
			exit_tryhelp(2);

		default:
			if (cs.target) {
				xtables_option_tpcall(c, argv,
						      invert, cs.target, &cs.fw);
			}
			break;
		}
		invert = FALSE;
	}

	if (cs.target)
		xtables_option_tfcall(cs.target);

	if (optind < argc)
		xtables_error(PARAMETER_PROBLEM,
			      "unknown arguments found on commandline");
	if (!command)
		xtables_error(PARAMETER_PROBLEM, "no command specified");
	if (invert)
		xtables_error(PARAMETER_PROBLEM,
			      "nothing appropriate following !");

	if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) {
		if (!(options & OPT_D_IP))
			dhostnetworkmask = "0.0.0.0/0";
		if (!(options & OPT_S_IP))
			shostnetworkmask = "0.0.0.0/0";
	}

	if (shostnetworkmask)
		parse_hostnetworkmask(shostnetworkmask, &saddrs,
				      &(cs.fw.arp.smsk), &nsaddrs);

	if (dhostnetworkmask)
		parse_hostnetworkmask(dhostnetworkmask, &daddrs,
				      &(cs.fw.arp.tmsk), &ndaddrs);

	if ((nsaddrs > 1 || ndaddrs > 1) &&
	    (cs.fw.arp.invflags & (ARPT_INV_SRCIP | ARPT_INV_TGTIP)))
		xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple"
				" source or destination IP addresses");

	if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
		xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
						 "specify a unique address");

	generic_opt_check(command, options);

	if (chain && strlen(chain) > ARPT_FUNCTION_MAXNAMELEN)
		xtables_error(PARAMETER_PROBLEM,
				"chain name `%s' too long (must be under %i chars)",
				chain, ARPT_FUNCTION_MAXNAMELEN);

	if (nft_init(h, xtables_arp) < 0)
		xtables_error(OTHER_PROBLEM,
			      "Could not initialize nftables layer.");

	h->ops = nft_family_ops_lookup(h->family);
	if (h->ops == NULL)
		xtables_error(PARAMETER_PROBLEM, "Unknown family");

	if (command == CMD_APPEND
	    || command == CMD_DELETE
	    || command == CMD_INSERT
	    || command == CMD_REPLACE) {
		if (strcmp(chain, "PREROUTING") == 0
		    || strcmp(chain, "INPUT") == 0) {
			/* -o not valid with incoming packets. */
			if (options & OPT_VIANAMEOUT)
				xtables_error(PARAMETER_PROBLEM,
					      "Can't use -%c with %s\n",
					      opt2char(OPT_VIANAMEOUT),
					      chain);
		}

		if (strcmp(chain, "POSTROUTING") == 0
		    || strcmp(chain, "OUTPUT") == 0) {
			/* -i not valid with outgoing packets */
			if (options & OPT_VIANAMEIN)
				xtables_error(PARAMETER_PROBLEM,
						"Can't use -%c with %s\n",
						opt2char(OPT_VIANAMEIN),
						chain);
		}

		if (!cs.target && strlen(cs.jumpto) != 0) {
			size_t size;

			cs.target = xtables_find_target(XT_STANDARD_TARGET,
							XTF_LOAD_MUST_SUCCEED);
			size = sizeof(struct arpt_entry_target) + cs.target->size;
			cs.target->t = xtables_calloc(1, size);
			cs.target->t->u.target_size = size;
			strcpy(cs.target->t->u.user.name, cs.jumpto);
		}
	}

	switch (command) {
	case CMD_APPEND:
		ret = append_entry(h, chain, *table, &cs, 0,
				   nsaddrs, saddrs, ndaddrs, daddrs,
				   options&OPT_VERBOSE, true);
		break;
	case CMD_DELETE:
		ret = delete_entry(chain, *table, &cs,
				   nsaddrs, saddrs, ndaddrs, daddrs,
				   options&OPT_VERBOSE, h);
		break;
	case CMD_DELETE_NUM:
		ret = nft_rule_delete_num(h, chain, *table, rulenum - 1, verbose);
		break;
	case CMD_REPLACE:
		ret = replace_entry(chain, *table, &cs, rulenum - 1,
				    saddrs, daddrs, options&OPT_VERBOSE, h);
		break;
	case CMD_INSERT:
		ret = append_entry(h, chain, *table, &cs, rulenum - 1,
				   nsaddrs, saddrs, ndaddrs, daddrs,
				   options&OPT_VERBOSE, false);
		break;
	case CMD_LIST:
		ret = list_entries(h, chain, *table,
				   rulenum,
				   options&OPT_VERBOSE,
				   options&OPT_NUMERIC,
				   /*options&OPT_EXPANDED*/0,
				   options&OPT_LINENUMBERS);
		break;
	case CMD_FLUSH:
		ret = nft_rule_flush(h, chain, *table);
		break;
	case CMD_ZERO:
		ret = nft_chain_zero_counters(h, chain, *table);
		break;
	case CMD_LIST|CMD_ZERO:
		ret = list_entries(h, chain, *table, rulenum,
				   options&OPT_VERBOSE,
				   options&OPT_NUMERIC,
				   /*options&OPT_EXPANDED*/0,
				   options&OPT_LINENUMBERS);
		if (ret)
			ret = nft_chain_zero_counters(h, chain, *table);
		break;
	case CMD_NEW_CHAIN:
		ret = nft_chain_user_add(h, chain, *table);
		break;
	case CMD_DELETE_CHAIN:
		ret = nft_chain_user_del(h, chain, *table);
		break;
	case CMD_RENAME_CHAIN:
		ret = nft_chain_user_rename(h, chain, *table, newname);
		break;
	case CMD_SET_POLICY:
		ret = nft_chain_set(h, *table, chain, policy, NULL);
		if (ret < 0)
			xtables_error(PARAMETER_PROBLEM, "Wrong policy `%s'\n",
				      policy);
		break;
	default:
		/* We should never reach this... */
		exit_tryhelp(2);
	}

/*	if (verbose > 1)
		dump_entries(*handle);*/

	return ret;
}