/** * gtags_first: return first record * * @param[in] gtop #GTOP structure * @param[in] pattern tag name <br> * - may be regular expression * - may be @VAR{NULL} * @param[in] flags #GTOP_PREFIX: prefix read <br> * #GTOP_KEY: read key only <br> * #GTOP_PATH: read path only <br> * #GTOP_NOREGEX: don't use regular expression. <br> * #GTOP_IGNORECASE: ignore case distinction. <br> * #GTOP_BASICREGEX: use basic regular expression. <br> * #GTOP_NOSORT: don't sort * @return record */ GTP * gtags_first(GTOP *gtop, const char *pattern, int flags) { int regflags = 0; static regex_t reg; const char *tagline; STATIC_STRBUF(regex); strbuf_clear(regex); gtop->preg = ® gtop->key = NULL; gtop->prefix = NULL; gtop->flags = flags; gtop->dbflags = 0; gtop->readcount = 1; /* Settlement for last time if any */ if (gtop->path_hash) { strhash_close(gtop->path_hash); gtop->path_hash = NULL; } if (gtop->path_array) { free(gtop->path_array); gtop->path_array = NULL; } if (flags & GTOP_KEY) gtop->dbflags |= DBOP_KEY; if (!(flags & GTOP_BASICREGEX)) regflags |= REG_EXTENDED; /* * decide a read method */ if (pattern == NULL) gtop->preg = NULL; else if (pattern[0] == 0) return NULL; else if (!strcmp(pattern, ".*") || !strcmp(pattern, "^.*$") || !strcmp(pattern, "^") || !strcmp(pattern, "$") || !strcmp(pattern, "^.*") || !strcmp(pattern, ".*$")) { /* * Since these regular expressions match to any record, * we take sequential read method. */ gtop->preg = NULL; } else if (flags & GTOP_IGNORECASE) { regflags |= REG_ICASE; if (!isregex(pattern) || flags & GTOP_NOREGEX) { gtop->prefix = get_prefix(pattern, flags); if (gtop->openflags & GTAGS_DEBUG) if (gtop->prefix != NULL) fprintf(stderr, "Using prefix: %s\n", gtop->prefix); if (gtop->prefix == NULL) die("gtags_first: impossible (1)."); strbuf_putc(regex, '^'); strbuf_puts(regex, pattern); if (!(flags & GTOP_PREFIX)) strbuf_putc(regex, '$'); } else if (*pattern == '^' && (gtop->prefix = get_prefix(pattern, flags)) != NULL) { if (gtop->openflags & GTAGS_DEBUG) fprintf(stderr, "Using prefix: %s\n", gtop->prefix); strbuf_puts(regex, pattern); } else { strbuf_puts(regex, pattern); } } else { if (!isregex(pattern) || flags & GTOP_NOREGEX) { if (flags & GTOP_PREFIX) gtop->dbflags |= DBOP_PREFIX; gtop->key = pattern; gtop->preg = NULL; } else if (*pattern == '^' && (gtop->key = get_prefix(pattern, flags)) != NULL) { if (gtop->openflags & GTAGS_DEBUG) fprintf(stderr, "Using prefix: %s\n", gtop->key); gtop->dbflags |= DBOP_PREFIX; gtop->preg = NULL; } else { strbuf_puts(regex, pattern); } } if (gtop->prefix) { if (gtop->key) die("gtags_first: impossible (2)."); gtop->key = gtop->prefix; gtop->dbflags |= DBOP_PREFIX; } if (strbuf_getlen(regex) > 0) { if (gtop->preg == NULL) die("gtags_first: impossible (3)."); if (regcomp(gtop->preg, strbuf_value(regex), regflags) != 0) die("invalid regular expression."); } /* * If GTOP_PATH is set, at first, we collect all path names in a pool and * sort them. gtags_first() and gtags_next() returns one of the pool. */ if (gtop->flags & GTOP_PATH) { struct sh_entry *entry; char *p; const char *cp; unsigned long i; gtop->path_hash = strhash_open(HASHBUCKETS); /* * Pool path names. * * fid path name * +-------------------------- * |100 ./aaa/a.c * |105 ./aaa/b.c * ... */ again0: for (tagline = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags); tagline != NULL; tagline = dbop_next(gtop->dbop)) { VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop); /* extract file id */ p = locatestring(tagline, " ", MATCH_FIRST); if (p == NULL) die("Invalid tag record. '%s'\n", tagline); *p = '\0'; entry = strhash_assign(gtop->path_hash, tagline, 1); /* new entry: get path name and set. */ if (entry->value == NULL) { cp = gpath_fid2path(tagline, NULL); if (cp == NULL) die("GPATH is corrupted.(file id '%s' not found)", tagline); entry->value = strhash_strdup(gtop->path_hash, cp, 0); } } if (gtop->prefix && gtags_restart(gtop)) goto again0; /* * Sort path names. * * fid path name path_array (sort) * +-------------------------- +---+ * |100 ./aaa/a.c <-------* | * |105 ./aaa/b.c <-------* | * ... ... */ gtop->path_array = (char **)check_malloc(gtop->path_hash->entries * sizeof(char *)); i = 0; for (entry = strhash_first(gtop->path_hash); entry != NULL; entry = strhash_next(gtop->path_hash)) gtop->path_array[i++] = entry->value; if (i != gtop->path_hash->entries) die("Something is wrong. 'i = %lu, entries = %lu'" , i, gtop->path_hash->entries); if (!(gtop->flags & GTOP_NOSORT)) qsort(gtop->path_array, gtop->path_hash->entries, sizeof(char *), compare_path); gtop->path_count = gtop->path_hash->entries; gtop->path_index = 0; if (gtop->path_index >= gtop->path_count) return NULL; gtop->gtp.path = gtop->path_array[gtop->path_index++]; return >op->gtp; } else if (gtop->flags & GTOP_KEY) { again1: for (gtop->gtp.tag = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags); gtop->gtp.tag != NULL; gtop->gtp.tag = dbop_next(gtop->dbop)) { VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop); break; } if (gtop->gtp.tag == NULL) { if (gtop->prefix && gtags_restart(gtop)) goto again1; } return gtop->gtp.tag ? >op->gtp : NULL; } else { if (gtop->vb == NULL) gtop->vb = varray_open(sizeof(GTP), 200); else varray_reset(gtop->vb); if (gtop->segment_pool == NULL) gtop->segment_pool = pool_open(); else pool_reset(gtop->segment_pool); if (gtop->path_hash == NULL) gtop->path_hash = strhash_open(HASHBUCKETS); else strhash_reset(gtop->path_hash); again2: tagline = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags); if (tagline == NULL) { if (gtop->prefix && gtags_restart(gtop)) goto again2; return NULL; } /* * Dbop_next() wil read the same record again. */ dbop_unread(gtop->dbop); /* * Read a tag segment with sorting. */ segment_read(gtop); return >op->gtp_array[gtop->gtp_index++]; } }
static int tcpm_do_cmd(int cmd, int argc, char **argv) { TCPM_REQUEST(req, 1024, TCP_METRICS_CMD_GET, NLM_F_REQUEST); int atype = -1, stype = -1; int ack; memset(&f, 0, sizeof(f)); f.daddr.bitlen = -1; f.daddr.family = preferred_family; f.saddr.bitlen = -1; f.saddr.family = preferred_family; switch (preferred_family) { case AF_UNSPEC: case AF_INET: case AF_INET6: break; default: fprintf(stderr, "Unsupported protocol family: %d\n", preferred_family); return -1; } for (; argc > 0; argc--, argv++) { if (strcmp(*argv, "src") == 0 || strcmp(*argv, "source") == 0) { char *who = *argv; NEXT_ARG(); if (matches(*argv, "help") == 0) usage(); if (f.saddr.bitlen >= 0) duparg2(who, *argv); get_prefix(&f.saddr, *argv, preferred_family); if (f.saddr.bytelen && f.saddr.bytelen * 8 == f.saddr.bitlen) { if (f.saddr.family == AF_INET) stype = TCP_METRICS_ATTR_SADDR_IPV4; else if (f.saddr.family == AF_INET6) stype = TCP_METRICS_ATTR_SADDR_IPV6; } if (stype < 0) { fprintf(stderr, "Error: a specific IP address is expected rather than \"%s\"\n", *argv); return -1; } } else { char *who = "address"; if (strcmp(*argv, "addr") == 0 || strcmp(*argv, "address") == 0) { who = *argv; NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (f.daddr.bitlen >= 0) duparg2(who, *argv); get_prefix(&f.daddr, *argv, preferred_family); if (f.daddr.bytelen && f.daddr.bytelen * 8 == f.daddr.bitlen) { if (f.daddr.family == AF_INET) atype = TCP_METRICS_ATTR_ADDR_IPV4; else if (f.daddr.family == AF_INET6) atype = TCP_METRICS_ATTR_ADDR_IPV6; } if ((CMD_DEL & cmd) && atype < 0) { fprintf(stderr, "Error: a specific IP address is expected rather than \"%s\"\n", *argv); return -1; } } argc--; argv++; } if (cmd == CMD_DEL && atype < 0) missarg("address"); /* flush for exact address ? Single del */ if (cmd == CMD_FLUSH && atype >= 0) cmd = CMD_DEL; /* flush for all addresses ? Single del without address */ if (cmd == CMD_FLUSH && f.daddr.bitlen <= 0 && f.saddr.bitlen <= 0 && preferred_family == AF_UNSPEC) { cmd = CMD_DEL; req.g.cmd = TCP_METRICS_CMD_DEL; ack = 1; } else if (cmd == CMD_DEL) { req.g.cmd = TCP_METRICS_CMD_DEL; ack = 1; } else { /* CMD_FLUSH, CMD_LIST */ ack = 0; } if (genl_family < 0) { if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) { fprintf(stderr, "Cannot open generic netlink socket\n"); exit(1); } genl_family = genl_resolve_family(&grth, TCP_METRICS_GENL_NAME); if (genl_family < 0) exit(1); req.n.nlmsg_type = genl_family; } if (!(cmd & CMD_FLUSH) && (atype >= 0 || (cmd & CMD_DEL))) { if (ack) req.n.nlmsg_flags |= NLM_F_ACK; if (atype >= 0) addattr_l(&req.n, sizeof(req), atype, &f.daddr.data, f.daddr.bytelen); if (stype >= 0) addattr_l(&req.n, sizeof(req), stype, &f.saddr.data, f.saddr.bytelen); } else { req.n.nlmsg_flags |= NLM_F_DUMP; } f.cmd = cmd; if (cmd & CMD_FLUSH) { int round = 0; char flushb[4096-512]; f.flushb = flushb; f.flushp = 0; f.flushe = sizeof(flushb); for (;;) { req.n.nlmsg_seq = grth.dump = ++grth.seq; if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) { perror("Failed to send flush request"); exit(1); } f.flushed = 0; if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (f.flushed == 0) { if (round == 0) { fprintf(stderr, "Nothing to flush.\n"); } else if (show_stats) printf("*** Flush is complete after %d round%s ***\n", round, round > 1 ? "s" : ""); fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); if (show_stats) { printf("\n*** Round %d, deleting %d entries ***\n", round, f.flushed); fflush(stdout); } } return 0; } if (ack) { if (rtnl_talk(&grth, &req.n, 0, 0, NULL) < 0) return -2; } else if (atype >= 0) { if (rtnl_talk(&grth, &req.n, 0, 0, &req.n) < 0) return -2; if (process_msg(NULL, &req.n, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } else { req.n.nlmsg_seq = grth.dump = ++grth.seq; if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) { perror("Failed to send dump request"); exit(1); } if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } return 0; }
static int iprule_modify(int cmd, int argc, char **argv) { int table_ok = 0; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset(&req, 0, sizeof(req)); req.n.nlmsg_type = cmd; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.r.rtm_family = preferred_family; req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_table = 0; req.r.rtm_type = RTN_UNSPEC; if (cmd == RTM_NEWRULE) { req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; req.r.rtm_type = RTN_UNICAST; } while (argc > 0) { if (strcmp(*argv, "from") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_src_len = dst.bitlen; addattr_l(&req.n, sizeof(req), RTA_SRC, &dst.data, dst.bytelen); } else if (strcmp(*argv, "to") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_dst_len = dst.bitlen; addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); } else if (matches(*argv, "preference") == 0 || matches(*argv, "order") == 0 || matches(*argv, "priority") == 0) { __u32 pref; NEXT_ARG(); if (get_u32(&pref, *argv, 0)) invarg("preference value is invalid\n", *argv); addattr32(&req.n, sizeof(req), RTA_PRIORITY, pref); } else if (strcmp(*argv, "tos") == 0) { __u32 tos; NEXT_ARG(); if (rtnl_dsfield_a2n(&tos, *argv)) invarg("TOS value is invalid\n", *argv); req.r.rtm_tos = tos; } else if (strcmp(*argv, "fwmark") == 0) { __u32 fwmark; NEXT_ARG(); if (get_u32(&fwmark, *argv, 0)) invarg("fwmark value is invalid\n", *argv); addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark); } else if (matches(*argv, "realms") == 0) { __u32 realm; NEXT_ARG(); if (get_rt_realms(&realm, *argv)) invarg("invalid realms\n", *argv); addattr32(&req.n, sizeof(req), RTA_FLOW, realm); } else if (matches(*argv, "table") == 0 || strcmp(*argv, "lookup") == 0) { __u32 tid; NEXT_ARG(); if (rtnl_rttable_a2n(&tid, *argv)) invarg("invalid table ID\n", *argv); req.r.rtm_table = tid; table_ok = 1; } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "iif") == 0) { NEXT_ARG(); addattr_l(&req.n, sizeof(req), RTA_IIF, *argv, strlen(*argv)+1); } else if (strcmp(*argv, "nat") == 0 || matches(*argv, "map-to") == 0) { NEXT_ARG(); fprintf(stderr, "Warning: route NAT is deprecated\n"); addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv)); req.r.rtm_type = RTN_NAT; } else { int type; if (strcmp(*argv, "type") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (rtnl_rtntype_a2n(&type, *argv)) invarg("Failed to parse rule type", *argv); req.r.rtm_type = type; } argc--; argv++; } if (req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; if (!table_ok && cmd == RTM_NEWRULE) req.r.rtm_table = RT_TABLE_MAIN; if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; return 0; }
int iproute_modify(int cmd, unsigned flags, int argc, char *argv) { REQ req; char mxbuf[256]; struct rtattr * mxrta = (void*)mxbuf; unsigned mxlock = 0; char *d = NULL; int gw_ok = 0; int dst_ok = 0; int nhs_ok = 0; int scope_ok = 0; int table_ok = 0; // int type_ok = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.r.rtm_family = preferred_family; req.r.rtm_table = RT_TABLE_MAIN; req.r.rtm_scope = RT_SCOPE_NOWHERE; if(cmd != RTM_DELROUTE) { req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; } mxrta->rta_type = RTA_METRICS; mxrta->rta_len = RTA_LENGTH(0); while (argc > 0) { if(strcmp(argv, "src") == 0) { inet_prefix addr; NEXT_ARG(); get_addr(&addr, argv, req.r.rtm_family); if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = addr.family; addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen); } else if(strcmp(argv, "via") == 0) { inet_prefix addr; gw_ok = 1; NEXT_ARG(); get_addr(&addr, argv, req.r.rtm_family); if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = addr.family; addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen); } else if(strcmp(argv, "from") == 0) { inet_prefix addr; NEXT_ARG(); get_prefix(&addr, argv, req.r.rtm_family); if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = addr.family; if(addr.bytelen) addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); req.r.rtm_src_len = addr.bitlen; } else if(strcmp(argv, "tos") == 0 || matches(argv, "dsfield") == 0) { __u32 tos; NEXT_ARG(); if(rtnl_dsfield_a2n(&tos, argv)) invarg("\"tos\" value is invalid\n", argv); req.r.rtm_tos = tos; } else if(matches(argv, "metric") == 0 || matches(argv, "priority") == 0 || matches(argv, "preference") == 0) { __u32 metric; NEXT_ARG(); if(get_u32(&metric, argv, 0)) invarg("\"metric\" value is invalid\n", argv); addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric); } else if(strcmp(argv, "scope") == 0) { __u32 scope = 0; NEXT_ARG(); if(rtnl_rtscope_a2n(&scope, argv)) invarg("invalid \"scope\" value\n", argv); req.r.rtm_scope = scope; scope_ok = 1; } else if(strcmp(argv, "mtu") == 0) { unsigned mtu; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_MTU); NEXT_ARG(); } if(get_unsigned(&mtu, argv, 0)) invarg("\"mtu\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); #ifdef RTAX_ADVMSS } else if(strcmp(argv, "advmss") == 0) { unsigned mss; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_ADVMSS); NEXT_ARG(); } if(get_unsigned(&mss, argv, 0)) invarg("\"mss\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_ADVMSS, mss); #endif #ifdef RTAX_REORDERING } else if(matches(argv, "reordering") == 0) { unsigned reord; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_REORDERING); NEXT_ARG(); } if(get_unsigned(&reord, argv, 0)) invarg("\"reordering\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord); #endif } else if(strcmp(argv, "rtt") == 0) { unsigned rtt; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_RTT); NEXT_ARG(); } if(get_unsigned(&rtt, argv, 0)) invarg("\"rtt\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, rtt); } else if(matches(argv, "window") == 0) { unsigned win; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_WINDOW); NEXT_ARG(); } if(get_unsigned(&win, argv, 0)) invarg("\"window\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_WINDOW, win); } else if(matches(argv, "cwnd") == 0) { unsigned win; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_CWND); NEXT_ARG(); } if(get_unsigned(&win, argv, 0)) invarg("\"cwnd\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_CWND, win); } else if(matches(argv, "rttvar") == 0) { unsigned win; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_RTTVAR); NEXT_ARG(); } if(get_unsigned(&win, argv, 0)) invarg("\"rttvar\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR, win); } else if(matches(argv, "ssthresh") == 0) { unsigned win; NEXT_ARG(); if(strcmp(argv, "lock") == 0) { mxlock |= (1<<RTAX_SSTHRESH); NEXT_ARG(); } if(get_unsigned(&win, argv, 0)) invarg("\"ssthresh\" value is invalid\n", argv); rta_addattr32(mxrta, sizeof(mxbuf), RTAX_SSTHRESH, win); // } else if(matches(argv, "realms") == 0) { // __u32 realm; // NEXT_ARG(); // if(get_rt_realms(&realm, argv)) // invarg("\"realm\" value is invalid\n", argv); // addattr32(&req.n, sizeof(req), RTA_FLOW, realm); } else if(strcmp(argv, "onlink") == 0) { req.r.rtm_flags |= RTNH_F_ONLINK; } else if(matches(argv, "equalize") == 0 || strcmp(argv, "eql") == 0) { req.r.rtm_flags |= RTM_F_EQUALIZE; } else if(strcmp(argv, "nexthop") == 0) { nhs_ok = 1; break; } else if(matches(argv, "protocol") == 0) { __u32 prot; NEXT_ARG(); if(rtnl_rtprot_a2n(&prot, argv)) invarg("\"protocol\" value is invalid\n", argv); req.r.rtm_protocol = prot; } else if(matches(argv, "table") == 0) { __u32 tid; NEXT_ARG(); if(rtnl_rttable_a2n(&tid, argv)) invarg("\"table\" value is invalid\n", argv); req.r.rtm_table = tid; table_ok = 1; } else if(strcmp(argv, "dev") == 0 || strcmp(argv, "oif") == 0) { NEXT_ARG(); d = argv; // } else if(strcmp(argv, "mpath") == 0 || // strcmp(argv, "mp") == 0) { // int i; // __u32 mp_alg = IP_MP_ALG_NONE; // // NEXT_ARG(); // for (i = 1; i < ARRAY_SIZE(mp_alg_names); i++) // if(strcmp(argv, mp_alg_names[i]) == 0) // mp_alg = i; // if(mp_alg == IP_MP_ALG_NONE) // invarg("\"mpath\" value is invalid\n", argv); // addattr_l(&req.n, sizeof(req), RTA_MP_ALGO, &mp_alg, sizeof(mp_alg)); } else { // int type; inet_prefix dst; if(strcmp(argv, "to") == 0) { NEXT_ARG(); } // if((*argv < '0' || *argv > '9') && // rtnl_rtntype_a2n(&type, argv) == 0) { // NEXT_ARG(); // req.r.rtm_type = type; // type_ok = 1; // } if(dst_ok) duparg2("to", argv); get_prefix(&dst, argv, req.r.rtm_family); if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = dst.family; req.r.rtm_dst_len = dst.bitlen; dst_ok = 1; if(dst.bytelen) addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); } argc--; argv++; } if(d || nhs_ok) { int idx; ll_init_map(&rth); if(d) { if((idx = ll_name_to_index(d)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); return -1; } addattr32(&req.n, sizeof(req), RTA_OIF, idx); } } if(mxrta->rta_len > RTA_LENGTH(0)) { if(mxlock) rta_addattr32(mxrta, sizeof(mxbuf), RTAX_LOCK, mxlock); addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); } if(nhs_ok) parse_nexthops(&req.n, &req.r, argc, argv); if(!table_ok) { if(req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_BROADCAST || req.r.rtm_type == RTN_NAT || req.r.rtm_type == RTN_ANYCAST) req.r.rtm_table = RT_TABLE_LOCAL; } if(!scope_ok) { if(req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT) req.r.rtm_scope = RT_SCOPE_HOST; else if(req.r.rtm_type == RTN_BROADCAST || req.r.rtm_type == RTN_MULTICAST || req.r.rtm_type == RTN_ANYCAST) req.r.rtm_scope = RT_SCOPE_LINK; else if(req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) { if(cmd == RTM_DELROUTE) req.r.rtm_scope = RT_SCOPE_NOWHERE; else if(!gw_ok && !nhs_ok) req.r.rtm_scope = RT_SCOPE_LINK; } } if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; if(rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); return 0; }
static int ipaddr_modify(int cmd, int argc, char **argv) { static const char *const option[] = { "peer", "remote", "broadcast", "brd", "anycast", "scope", "dev", "label", "local", 0 }; struct rtnl_handle rth; struct { struct nlmsghdr n; struct ifaddrmsg ifa; char buf[256]; } req; char *d = NULL; char *l = NULL; inet_prefix lcl; inet_prefix peer; int local_len = 0; int peer_len = 0; int brd_len = 0; int any_len = 0; int scoped = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.ifa.ifa_family = preferred_family; while (argc > 0) { const int option_num = index_in_str_array(option, *argv); switch (option_num) { case 0: /* peer */ case 1: /* remote */ NEXT_ARG(); if (peer_len) { duparg("peer", *argv); } get_prefix(&peer, *argv, req.ifa.ifa_family); peer_len = peer.bytelen; if (req.ifa.ifa_family == AF_UNSPEC) { req.ifa.ifa_family = peer.family; } addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen); req.ifa.ifa_prefixlen = peer.bitlen; break; case 2: /* broadcast */ case 3: /* brd */ { inet_prefix addr; NEXT_ARG(); if (brd_len) { duparg("broadcast", *argv); } if (LONE_CHAR(*argv, '+')) { brd_len = -1; } else if (LONE_DASH(*argv)) { brd_len = -2; } else { get_addr(&addr, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = addr.family; addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen); brd_len = addr.bytelen; } break; } case 4: /* anycast */ { inet_prefix addr; NEXT_ARG(); if (any_len) { duparg("anycast", *argv); } get_addr(&addr, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) { req.ifa.ifa_family = addr.family; } addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); any_len = addr.bytelen; break; } case 5: /* scope */ { uint32_t scope = 0; NEXT_ARG(); if (rtnl_rtscope_a2n(&scope, *argv)) { invarg(*argv, "scope"); } req.ifa.ifa_scope = scope; scoped = 1; break; } case 6: /* dev */ NEXT_ARG(); d = *argv; break; case 7: /* label */ NEXT_ARG(); l = *argv; addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1); break; case 8: /* local */ NEXT_ARG(); default: if (local_len) { duparg2("local", *argv); } get_prefix(&lcl, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) { req.ifa.ifa_family = lcl.family; } addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); local_len = lcl.bytelen; } argc--; argv++; } if (d == NULL) { bb_error_msg(bb_msg_requires_arg,"\"dev\""); return -1; } if (l && matches(d, l) != 0) { bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l); } if (peer_len == 0 && local_len && cmd != RTM_DELADDR) { peer = lcl; addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen); } if (req.ifa.ifa_prefixlen == 0) req.ifa.ifa_prefixlen = lcl.bitlen; if (brd_len < 0 && cmd != RTM_DELADDR) { inet_prefix brd; int i; if (req.ifa.ifa_family != AF_INET) { bb_error_msg("broadcast can be set only for IPv4 addresses"); return -1; } brd = peer; if (brd.bitlen <= 30) { for (i=31; i>=brd.bitlen; i--) { if (brd_len == -1) brd.data[0] |= htonl(1<<(31-i)); else brd.data[0] &= ~htonl(1<<(31-i)); } addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen); brd_len = brd.bytelen; } } if (!scoped && cmd != RTM_DELADDR) req.ifa.ifa_scope = default_scope(&lcl); if (rtnl_open(&rth, 0) < 0) exit(1); ll_init_map(&rth); if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) { bb_error_msg("cannot find device \"%s\"", d); return -1; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); exit(0); }
static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm *p) { int count = 0; char medium[IFNAMSIZ]; memset(medium, 0, sizeof(medium)); while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipv6/ipv6") == 0 || strcmp(*argv, "ip6ip6") == 0) p->proto = IPPROTO_IPV6; else if (strcmp(*argv, "ip/ipv6") == 0 || strcmp(*argv, "ipv4/ipv6") == 0 || strcmp(*argv, "ipip6") == 0 || strcmp(*argv, "ip4ip6") == 0) p->proto = IPPROTO_IPIP; else if (strcmp(*argv, "any/ipv6") == 0 || strcmp(*argv, "any") == 0) p->proto = 0; else { fprintf(stderr,"Cannot guess tunnel mode.\n"); exit(-1); } } else if (strcmp(*argv, "remote") == 0) { inet_prefix raddr; NEXT_ARG(); get_prefix(&raddr, *argv, preferred_family); if (raddr.family == AF_UNSPEC) invarg("\"remote\" address family is AF_UNSPEC", *argv); memcpy(&p->raddr, &raddr.data, sizeof(p->raddr)); } else if (strcmp(*argv, "local") == 0) { inet_prefix laddr; NEXT_ARG(); get_prefix(&laddr, *argv, preferred_family); if (laddr.family == AF_UNSPEC) invarg("\"local\" address family is AF_UNSPEC", *argv); memcpy(&p->laddr, &laddr.data, sizeof(p->laddr)); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(medium, *argv, IFNAMSIZ - 1); } else if (strcmp(*argv, "encaplimit") == 0) { NEXT_ARG(); if (strcmp(*argv, "none") == 0) { p->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT; } else { __u8 uval; if (get_u8(&uval, *argv, 0) < -1) invarg("invalid ELIM", *argv); p->encap_limit = uval; } } else if (strcmp(*argv, "hoplimit") == 0 || strcmp(*argv, "ttl") == 0 || strcmp(*argv, "hlim") == 0) { __u8 uval; NEXT_ARG(); if (get_u8(&uval, *argv, 0)) invarg("invalid TTL", *argv); p->hop_limit = uval; } else if (strcmp(*argv, "tclass") == 0 || strcmp(*argv, "tc") == 0 || strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) { __u8 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") == 0) p->flags |= IP6_TNL_F_USE_ORIG_TCLASS; else { if (get_u8(&uval, *argv, 16)) invarg("invalid TClass", *argv); p->flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; p->flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; } } else if (strcmp(*argv, "flowlabel") == 0 || strcmp(*argv, "fl") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") == 0) p->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; else { if (get_u32(&uval, *argv, 16)) invarg("invalid Flowlabel", *argv); if (uval > 0xFFFFF) invarg("invalid Flowlabel", *argv); p->flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; p->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; } } else if (strcmp(*argv, "dscp") == 0) { NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) invarg("not inherit", *argv); p->flags |= IP6_TNL_F_RCV_DSCP_COPY; } else { if (strcmp(*argv, "name") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (p->name[0]) duparg2("name", *argv); strncpy(p->name, *argv, IFNAMSIZ - 1); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip6_tnl_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (tnl_get_ioctl(*argv, &old_p)) return -1; *p = old_p; } } count++; argc--; argv++; } if (medium[0]) { p->link = tnl_ioctl_get_ifindex(medium); if (p->link == 0) return -1; } return 0; }
int main(int argc, char **argv) { ReadSeq read; gzFile gzf, out_gzf; long rec_num, line_num, n_err; int file_num = 0; char min_qual, max_qual; char *input_filename, *output_dir, *prefix; char output_filename[MAX_LINE]; int n_written; if(argc != 3) { fprintf(stderr, "usage: %s <fastq_file.txt.gz> <output_dir>\n", argv[0]); exit(2); } input_filename = argv[1]; output_dir = argv[2]; gzf = util_must_gzopen(input_filename, "rb"); prefix = get_prefix(output_dir, input_filename); rec_num = 0; line_num = 1; n_err = 0; min_qual = max_qual = -1; out_gzf = NULL; rec_num = 0; while(TRUE) { long r = 0; r = parse_fastq_read(&read, gzf); if(r == FASTQ_END) { /* we have reached the end of the file */ break; } if(r == FASTQ_ERR) { my_warn("%s:%d: invalid fastq record starting on line %ld:\n", __FILE__, __LINE__, line_num); n_err += 1; fprintf(stderr, " %s\n %s\n %s\n %s\n", read.line1, read.line2, read.line3, read.line4); } if(r == FASTQ_OK) { /* record max and min quality values observed */ if((min_qual == -1) || (min_qual > read.min_qual)) { min_qual = read.min_qual; } if((max_qual == -1) || (max_qual < read.max_qual)) { max_qual = read.max_qual; } if(out_gzf == NULL || rec_num > READS_PER_FILE) { if(out_gzf) { /* close old output file */ fprintf(stderr, "\n"); gzclose(out_gzf); } file_num += 1; n_written = snprintf(output_filename, MAX_LINE, "%s.%d.txt.gz", prefix, file_num); if(n_written > MAX_LINE) { my_err("%s:%d: filename too long\n", __FILE__, __LINE__); } fprintf(stderr, "writing to file '%s'\n", output_filename); out_gzf = util_must_gzopen(output_filename, "wb"); rec_num = 0; } /* write record to file */ n_written = gzprintf(out_gzf, "%s\n%s\n%s\n%s\n", read.line1, read.line2, read.line3, read.line4); if(n_written == 0) { my_err("%s:%d: failed to write to output file", __FILE__, __LINE__); } rec_num += 1; } line_num += 4; if((rec_num % 100000) == 0) { fprintf(stderr, "."); } } report_qual_type(min_qual, max_qual); fprintf(stderr, "\n"); fprintf(stderr, "fastq records: written=%ld, errors=%ld\n", rec_num, n_err); gzclose(gzf); if(out_gzf) { gzclose(out_gzf); } my_free(prefix); return 0; }
int ipaddr_modify(int cmd, int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct ifaddrmsg ifa; char buf[256]; } req; char *d = NULL; char *l = NULL; char *lcl_arg = NULL; inet_prefix lcl; inet_prefix peer; int local_len = 0; int peer_len = 0; int brd_len = 0; int any_len = 0; int scoped = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.ifa.ifa_family = preferred_family; while (argc > 0) { if (strcmp(*argv, "peer") == 0 || strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (peer_len) duparg("peer", *argv); get_prefix(&peer, *argv, req.ifa.ifa_family); peer_len = peer.bytelen; if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = peer.family; addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen); req.ifa.ifa_prefixlen = peer.bitlen; } else if (matches(*argv, "broadcast") == 0 || strcmp(*argv, "brd") == 0) { inet_prefix addr; NEXT_ARG(); if (brd_len) duparg("broadcast", *argv); if (strcmp(*argv, "+") == 0) brd_len = -1; else if (strcmp(*argv, "-") == 0) brd_len = -2; else { get_addr(&addr, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = addr.family; addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen); brd_len = addr.bytelen; } } else if (strcmp(*argv, "anycast") == 0) { inet_prefix addr; NEXT_ARG(); if (any_len) duparg("anycast", *argv); get_addr(&addr, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = addr.family; addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); any_len = addr.bytelen; } else if (strcmp(*argv, "scope") == 0) { int scope = 0; NEXT_ARG(); if (rtnl_rtscope_a2n(&scope, *argv)) invarg(*argv, "invalid scope value."); req.ifa.ifa_scope = scope; scoped = 1; } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); d = *argv; } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); l = *argv; addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1); } else { if (strcmp(*argv, "local") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (local_len) duparg2("local", *argv); lcl_arg = *argv; get_prefix(&lcl, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = lcl.family; addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); local_len = lcl.bytelen; } argc--; argv++; } if (d == NULL) { fprintf(stderr, "Not enough information: \"dev\" argument is required.\n"); return -1; } if (l && matches(d, l) != 0) { fprintf(stderr, "\"dev\" (%s) must match \"label\" (%s).\n", d, l); exit(1); } if (peer_len == 0 && local_len) { if (cmd == RTM_DELADDR && lcl.family == AF_INET && !(lcl.flags & PREFIXLEN_SPECIFIED)) { fprintf(stderr, "Warning: Executing wildcard deletion to stay compatible with old scripts.\n" \ " Explicitly specify the prefix length (%s/%d) to avoid this warning.\n" \ " This special behaviour is likely to disappear in further releases,\n" \ " fix your scripts!\n", lcl_arg, local_len*8); } else { peer = lcl; addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen); } } if (req.ifa.ifa_prefixlen == 0) req.ifa.ifa_prefixlen = lcl.bitlen; if (brd_len < 0 && cmd != RTM_DELADDR) { inet_prefix brd; int i; if (req.ifa.ifa_family != AF_INET) { fprintf(stderr, "Broadcast can be set only for IPv4 addresses\n"); return -1; } brd = peer; if (brd.bitlen <= 30) { for (i=31; i>=brd.bitlen; i--) { if (brd_len == -1) brd.data[0] |= htonl(1<<(31-i)); else brd.data[0] &= ~htonl(1<<(31-i)); } addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen); brd_len = brd.bytelen; } } if (!scoped && cmd != RTM_DELADDR) req.ifa.ifa_scope = default_scope(&lcl); if (rtnl_open(&rth, 0) < 0) exit(1); ll_init_map(&rth); if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); return -1; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); exit(0); }
static int ipaddrlabel_modify(int cmd, int argc, char **argv) { struct { struct nlmsghdr n; struct ifaddrlblmsg ifal; char buf[1024]; } req = { .n.nlmsg_type = cmd, .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg)), .n.nlmsg_flags = NLM_F_REQUEST, .ifal.ifal_family = preferred_family, }; inet_prefix prefix = {}; uint32_t label = 0xffffffffUL; char *p = NULL; char *l = NULL; if (cmd == RTM_NEWADDRLABEL) { req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; } while (argc > 0) { if (strcmp(*argv, "prefix") == 0) { NEXT_ARG(); p = *argv; get_prefix(&prefix, *argv, preferred_family); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if ((req.ifal.ifal_index = ll_name_to_index(*argv)) == 0) invarg("dev is invalid\n", *argv); } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); l = *argv; if (get_u32(&label, *argv, 0) || label == 0xffffffffUL) invarg("label is invalid\n", *argv); } argc--; argv++; } if (p == NULL) { fprintf(stderr, "Not enough information: \"prefix\" argument is required.\n"); return -1; } if (l == NULL) { fprintf(stderr, "Not enough information: \"label\" argument is required.\n"); return -1; } addattr32(&req.n, sizeof(req), IFAL_LABEL, label); addattr_l(&req.n, sizeof(req), IFAL_ADDRESS, &prefix.data, prefix.bytelen); req.ifal.ifal_prefixlen = prefix.bitlen; if (req.ifal.ifal_family == AF_UNSPEC) req.ifal.ifal_family = AF_INET6; if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) return -2; return 0; } static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rtnl_handle rth2; struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[IFAL_MAX+1]; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) return -1; parse_rtattr(tb, IFAL_MAX, RTM_RTA(r), len); if (tb[IFAL_ADDRESS]) { n->nlmsg_type = RTM_DELADDRLABEL; n->nlmsg_flags = NLM_F_REQUEST; if (rtnl_open(&rth2, 0) < 0) return -1; if (rtnl_talk(&rth2, n, NULL, 0) < 0) return -2; rtnl_close(&rth2); } return 0; } static int ipaddrlabel_flush(int argc, char **argv) { int af = preferred_family; if (af == AF_UNSPEC) af = AF_INET6; if (argc > 0) { fprintf(stderr, "\"ip addrlabel flush\" does not allow extra arguments\n"); return -1; } if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) { perror("Cannot send dump request"); return -1; } if (rtnl_dump_filter(&rth, flush_addrlabel, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); return -1; } return 0; }
static int iprule_modify(int cmd, int argc, char **argv) { int table_ok = 0; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset(&req, 0, sizeof(req)); req.n.nlmsg_type = cmd; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.r.rtm_family = preferred_family; req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_table = 0; req.r.rtm_type = RTN_UNSPEC; req.r.rtm_flags = 0; if (cmd == RTM_NEWRULE) { req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; req.r.rtm_type = RTN_UNICAST; } while (argc > 0) { if (strcmp(*argv, "not") == 0) { req.r.rtm_flags |= FIB_RULE_INVERT; } else if (strcmp(*argv, "from") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_src_len = dst.bitlen; addattr_l(&req.n, sizeof(req), FRA_SRC, &dst.data, dst.bytelen); } else if (strcmp(*argv, "to") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_dst_len = dst.bitlen; addattr_l(&req.n, sizeof(req), FRA_DST, &dst.data, dst.bytelen); } else if (matches(*argv, "preference") == 0 || matches(*argv, "order") == 0 || matches(*argv, "priority") == 0) { __u32 pref; NEXT_ARG(); if (get_u32(&pref, *argv, 0)) invarg("preference value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_PRIORITY, pref); } else if (strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) { __u32 tos; NEXT_ARG(); if (rtnl_dsfield_a2n(&tos, *argv)) invarg("TOS value is invalid\n", *argv); req.r.rtm_tos = tos; } else if (strcmp(*argv, "fwmark") == 0) { char *slash; __u32 fwmark, fwmask; NEXT_ARG(); if ((slash = strchr(*argv, '/')) != NULL) *slash = '\0'; if (get_u32(&fwmark, *argv, 0)) invarg("fwmark value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark); if (slash) { if (get_u32(&fwmask, slash+1, 0)) invarg("fwmask value is invalid\n", slash+1); addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask); } } else if (matches(*argv, "realms") == 0) { __u32 realm; NEXT_ARG(); if (get_rt_realms_or_raw(&realm, *argv)) invarg("invalid realms\n", *argv); addattr32(&req.n, sizeof(req), FRA_FLOW, realm); } else if (matches(*argv, "table") == 0 || strcmp(*argv, "lookup") == 0) { __u32 tid; NEXT_ARG(); if (rtnl_rttable_a2n(&tid, *argv)) invarg("invalid table ID\n", *argv); if (tid < 256) req.r.rtm_table = tid; else { req.r.rtm_table = RT_TABLE_UNSPEC; addattr32(&req.n, sizeof(req), FRA_TABLE, tid); } table_ok = 1; } else if (matches(*argv, "suppress_prefixlength") == 0 || strcmp(*argv, "sup_pl") == 0) { int pl; NEXT_ARG(); if (get_s32(&pl, *argv, 0) || pl < 0) invarg("suppress_prefixlength value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_SUPPRESS_PREFIXLEN, pl); } else if (matches(*argv, "suppress_ifgroup") == 0 || strcmp(*argv, "sup_group") == 0) { NEXT_ARG(); int group; if (rtnl_group_a2n(&group, *argv)) invarg("Invalid \"suppress_ifgroup\" value\n", *argv); addattr32(&req.n, sizeof(req), FRA_SUPPRESS_IFGROUP, group); } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "iif") == 0) { NEXT_ARG(); addattr_l(&req.n, sizeof(req), FRA_IFNAME, *argv, strlen(*argv)+1); } else if (strcmp(*argv, "oif") == 0) { NEXT_ARG(); addattr_l(&req.n, sizeof(req), FRA_OIFNAME, *argv, strlen(*argv)+1); } else if (strcmp(*argv, "nat") == 0 || matches(*argv, "map-to") == 0) { NEXT_ARG(); fprintf(stderr, "Warning: route NAT is deprecated\n"); addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv)); req.r.rtm_type = RTN_NAT; } else { int type; if (strcmp(*argv, "type") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); else if (matches(*argv, "goto") == 0) { __u32 target; type = FR_ACT_GOTO; NEXT_ARG(); if (get_u32(&target, *argv, 0)) invarg("invalid target\n", *argv); addattr32(&req.n, sizeof(req), FRA_GOTO, target); } else if (matches(*argv, "nop") == 0) type = FR_ACT_NOP; else if (rtnl_rtntype_a2n(&type, *argv)) invarg("Failed to parse rule type", *argv); req.r.rtm_type = type; table_ok = 1; } argc--; argv++; } if (req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; if (!table_ok && cmd == RTM_NEWRULE) req.r.rtm_table = RT_TABLE_MAIN; if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) return -2; return 0; }
//static inline num_result_t parse_number(const char* c, size_t i){ num_result_t num_result; num_result.type = CH_NO_TYPE; if( c[i] == '\0'){ return num_result; } uint64_t uint_accumulator = 0; int64_t int_accumulator = 0; double float_accumulator = 0; double float_base_accumulator = 1; int64_t sign = 1; char prefix = 0; size_t state = STATE_INIT; for( ; state != STATE_NONE_FOUND && state != STATE_FINISHED_INT && state != STATE_FINISHED_UINT && state != STATE_FINISHED_FLOAT; i++ ){ switch(state){ case STATE_INIT:{ uint_accumulator = 0; float_accumulator = 0; float_base_accumulator = 1; sign = 1; if( c[i] == '-') { sign = -1; state = STATE_FOUND_SIGN; continue; } if( c[i] == '+') { state = STATE_FOUND_SIGN; continue; } if( c[i] == '.') { state = STATE_GET_FLO_DIGITS; continue; } if( c[i] == '0') { state = STATE_FOUND_INIT_ZERO; continue; } if( isdigit(c[i]) ) { uint_accumulator = (c[i] - '0'); state = STATE_GET_DEC_DIGITS; continue; } if( iswhite(c[i]) ) { state = STATE_INIT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_FOUND_SIGN:{ if( c[i] == '0' ) { state = STATE_MUST_BE_ZERO_OR_PERIOD; continue; } if( c[i] == '.' ) { state = STATE_GET_FLO_DIGITS; continue; } if( isdigit(c[i]) ) { uint_accumulator = (c[i] - '0'); state = STATE_GET_DEC_DIGITS; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_MUST_BE_ZERO_OR_PERIOD: { if( c[i] == '0' ) { state = STATE_MUST_BE_ZERO_OR_PERIOD; continue; } if( c[i] == '.' ) { state = STATE_GET_FLO_DIGITS; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_FOUND_INIT_ZERO: { if( c[i] == 'x') { state = STATE_GET_HEX_DIGITS; continue; } if( c[i] == 'X') { state = STATE_GET_HEX_DIGITS; continue; } if( c[i] == 'b') { state = STATE_GET_BIN_DIGITS; continue; } if( c[i] == 'B') { state = STATE_GET_BIN_DIGITS; continue; } if( c[i] == '.') { state = STATE_GET_FLO_DIGITS; continue; } if( c[i] == '\0') { state = STATE_FINISHED_UINT; continue; } if( isprefix(c[i])) { prefix = c[i]; state = STATE_END_UINT; continue; } if( isodigit(c[i])) { uint_accumulator = (c[i] - '0'); state = STATE_GET_OCT_DIGITS; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_GET_DEC_DIGITS:{ if( isdigit(c[i]) ) { uint_accumulator *= 10; uint_accumulator += c[i] - '0'; state = STATE_GET_DEC_DIGITS; continue; } if( c[i] == '.') { float_accumulator = (double)uint_accumulator; state = STATE_GET_FLO_DIGITS; continue; } if( isprefix(c[i])) { prefix = c[i]; state = STATE_END_UINT; continue; } if( issci(c[i]) ) if( iswhite(c[i]) ) { state = STATE_END_UINT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_UINT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_GET_BIN_DIGITS: { if( isbdigit(c[i]) ) { uint_accumulator <<= 1; uint_accumulator += c[i] - '0'; state = STATE_GET_BIN_DIGITS; continue; } if( isprefix(c[i])) { prefix = c[i]; state = STATE_END_UINT; continue; } if( iswhite(c[i]) ) { state = STATE_END_UINT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_UINT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_GET_OCT_DIGITS: { if( isodigit(c[i]) ) { uint_accumulator *= 8; uint_accumulator += c[i] - '0'; state = STATE_GET_OCT_DIGITS; continue; } if( isprefix(c[i])) { prefix = c[i]; state = STATE_END_UINT; continue; } if( iswhite(c[i]) ) { state = STATE_END_UINT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_UINT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_GET_HEX_DIGITS: { if( isdigit(c[i]) ) { uint_accumulator *= 16; uint_accumulator += c[i] - '0'; state = STATE_GET_HEX_DIGITS; continue; } if( isxdigit(c[i]) ) { uint_accumulator *= 16; uint_accumulator += getxdigit(c[i]); state = STATE_GET_HEX_DIGITS; continue; } if( isprefix(c[i])) { prefix = c[i]; state = STATE_END_UINT; continue; } if( iswhite(c[i]) ) { state = STATE_END_UINT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_UINT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_GET_FLO_DIGITS: { if( isdigit(c[i]) ) { float_base_accumulator *= 10.0; float_accumulator += (double)(c[i] - '0') / float_base_accumulator; state = STATE_GET_FLO_DIGITS; continue; } if( isprefix(c[i])) { prefix = c[i]; state = STATE_END_FLOAT; continue; } if( iswhite(c[i]) ) { state = STATE_END_FLOAT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_FLOAT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_END_UINT:{ if( iswhite(c[i]) ) { state = STATE_END_UINT; continue; } if( isbin( c[i]) && isprefix(prefix)) { uint_accumulator *= get_bin_prefix(prefix); state = STATE_FINISHED_UINT; continue; } if( isprefix(prefix)) { uint_accumulator *= get_prefix(prefix); state = STATE_FINISHED_UINT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_UINT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_END_INT: { if( iswhite(c[i]) ) { state = STATE_END_INT; continue; } if( isprefix(prefix)) { int_accumulator *= get_prefix(prefix); state = STATE_FINISHED_INT; continue; } if( isbin(c[i]) && isprefix(prefix)) { int_accumulator *= get_bin_prefix(prefix); state = STATE_FINISHED_INT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_INT; continue; } else { state = STATE_NONE_FOUND; continue; } } case STATE_END_FLOAT: { if( iswhite(c[i]) ) { state = STATE_END_FLOAT; continue; } if( isprefix(prefix)) { float_accumulator *= get_prefix(prefix); state = STATE_FINISHED_FLOAT; continue; } if( isbin( c[i] && isprefix(prefix))) { float_accumulator *= get_bin_prefix(prefix); state = STATE_FINISHED_FLOAT; continue; } if( isnull(c[i]) ) { state = STATE_FINISHED_FLOAT; continue; } else { state = STATE_NONE_FOUND; continue; } } default:{ ch_log_error("Undefined state parsing numeric %lu\n", state); num_result.type = CH_NO_TYPE; return num_result; } } } switch(state){ case STATE_NONE_FOUND:{ num_result.type = CH_NO_TYPE; break; } case STATE_FINISHED_INT: { num_result.type = CH_INT64; num_result.val_int = int_accumulator; break; } case STATE_FINISHED_UINT:{ if(sign == -1){ int_accumulator = uint_accumulator * sign; num_result.type = CH_INT64; num_result.val_int = int_accumulator; break; } num_result.type = CH_UINT64; num_result.val_uint = uint_accumulator; break; } case STATE_FINISHED_FLOAT:{ num_result.type = CH_DOUBLE; num_result.val_dble = float_accumulator * (double)sign; break; } default:{ ch_log_error("Undefined state parsing numeric %lu\n", state); num_result.type = CH_NO_TYPE; return num_result; } } return num_result; }
int popc_logger_t(LOGLEVEL level, const char* file, int line, const char* function, const char* tag, const char* format, ...) { // Check if message level in higher than our threshold if (level < MIN_LOG_LEVEL) return 0; // Use file name without path to avoid having the full user path in logs const char* basename = strrchr(file, '/'); if (basename == nullptr) basename = file; else basename += 1; auto log_file = get_log_file(); // Time time_t rawtime; time(&rawtime); const tm* timeinfo = localtime(&rawtime); char dd[20]; strftime(dd, sizeof(dd), "%Y-%m-%d %H:%M:%S", timeinfo); char msg[512]; va_list ap; va_start(ap, format); vsnprintf(msg, sizeof(msg), format, ap); va_end(ap); auto msg_length = strlen(msg); if (msg[msg_length - 1] == '\n') { msg[msg_length - 1] = ' '; } // Print the message to stderr or stdout if (level >= MIN_STDERR_LEVEL) if (tag) { fprintf(stderr, "%s %5d %s [%5s] %s (%s:%d %s)\n", dd, getpid(), get_prefix(level), tag, msg, basename, line, function); } else { fprintf(stderr, "%s %5d %s %s (%s:%d %s)\n", dd, getpid(), get_prefix(level), msg, basename, line, function); } else if (level >= MIN_STDOUT_LEVEL) fprintf(stdout, "%s\n", msg); // Print the message to file FILE* f = fopen(log_file.c_str(), "a"); if (f == NULL) { fprintf(stderr, "ERROR: Impossible to open log file %s\n", log_file.c_str()); return 1; } if (tag) { fprintf(f, "%s %5d %s [%5s] %s (%s:%d %s)\n", dd, getpid(), get_prefix(level), tag, msg, basename, line, function); } else { fprintf(f, "%s %5d %s %s (%s:%d %s)\n", dd, getpid(), get_prefix(level), msg, basename, line, function); } fclose(f); return 0; }
REQ iproute_get(int argc, char *argv) { REQ req; char *idev = NULL; char *odev = NULL; int connected = 0; int from_ok = 0; memset(&req, 0, sizeof(req)); iproute_reset_filter(); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETROUTE; req.r.rtm_family = preferred_family; req.r.rtm_table = 0; req.r.rtm_protocol = 0; req.r.rtm_scope = 0; req.r.rtm_type = 0; req.r.rtm_src_len = 0; req.r.rtm_dst_len = 0; req.r.rtm_tos = 0; while (argc > 0) { if(strcmp(argv, "tos") == 0 || matches(argv, "dsfield") == 0) { __u32 tos; NEXT_ARG(); if(rtnl_dsfield_a2n(&tos, argv)) invarg("TOS value is invalid\n", argv); req.r.rtm_tos = tos; } else if(matches(argv, "from") == 0) { inet_prefix addr; NEXT_ARG(); from_ok = 1; get_prefix(&addr, argv, req.r.rtm_family); if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = addr.family; if(addr.bytelen) addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); req.r.rtm_src_len = addr.bitlen; } else if(matches(argv, "iif") == 0) { NEXT_ARG(); idev = argv; } else if(matches(argv, "oif") == 0 || strcmp(argv, "dev") == 0) { NEXT_ARG(); odev = argv; } else if(matches(argv, "notify") == 0) { req.r.rtm_flags |= RTM_F_NOTIFY; } else if(matches(argv, "connected") == 0) { connected = 1; } else { inet_prefix addr; if(strcmp(argv, "to") == 0) { NEXT_ARG(); } get_prefix(&addr, argv, req.r.rtm_family); if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = addr.family; if(addr.bytelen) addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen); req.r.rtm_dst_len = addr.bitlen; } argc--; argv++; } if(req.r.rtm_dst_len == 0) { fprintf(stderr, "need at least destination address\n"); exit(1); } ll_init_map(&rth); if(idev || odev) { int idx; if(idev) { if((idx = ll_name_to_index(idev)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", idev); //return -1; exit(1); } addattr32(&req.n, sizeof(req), RTA_IIF, idx); } if(odev) { if((idx = ll_name_to_index(odev)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", odev); //return -1; exit(1); } addattr32(&req.n, sizeof(req), RTA_OIF, idx); } } if(req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; if(rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) exit(2); if(connected && !from_ok) { struct rtmsg *r = NLMSG_DATA(&req.n); int len = req.n.nlmsg_len; struct rtattr * tb[RTA_MAX+1]; // if(print_route(NULL, &req.n, (void*)stdout) < 0) { // fprintf(stderr, "An error :-)\n"); // exit(1); // } if(req.n.nlmsg_type != RTM_NEWROUTE) { fprintf(stderr, "Not a route?\n"); //return -1; exit(1); } len -= NLMSG_LENGTH(sizeof(*r)); if(len < 0) { fprintf(stderr, "Wrong len %d\n", len); //return -1; exit(1); } parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); if(tb[RTA_PREFSRC]) { tb[RTA_PREFSRC]->rta_type = RTA_SRC; r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]); } else if(!tb[RTA_SRC]) { fprintf(stderr, "Failed to connect the route\n"); //return -1; exit(1); } if(!odev && tb[RTA_OIF]) tb[RTA_OIF]->rta_type = 0; if(tb[RTA_GATEWAY]) tb[RTA_GATEWAY]->rta_type = 0; if(!idev && tb[RTA_IIF]) tb[RTA_IIF]->rta_type = 0; req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETROUTE; if(rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) exit(2); } // if(print_route(NULL, &req.n, (void*)stdout) < 0) { // fprintf(stderr, "An error :-)\n"); // exit(1); // } // exit(0); return req; }
static int do_show_or_flush(int argc, char **argv, int flush) { char *filter_dev = NULL; int state_given = 0; struct ndmsg ndm = { 0 }; ipneigh_reset_filter(0); if (!filter.family) filter.family = preferred_family; if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); return -1; } filter.state = ~(NUD_PERMANENT|NUD_NOARP); } else filter.state = 0xFF & ~NUD_NOARP; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (filter_dev) duparg("dev", *argv); filter_dev = *argv; } else if (strcmp(*argv, "unused") == 0) { filter.unused_only = 1; } else if (strcmp(*argv, "nud") == 0) { unsigned state; NEXT_ARG(); if (!state_given) { state_given = 1; filter.state = 0; } if (nud_state_a2n(&state, *argv)) { if (strcmp(*argv, "all") != 0) invarg("nud state is bad", *argv); state = ~0; if (flush) state &= ~NUD_NOARP; } if (state == 0) state = 0x100; filter.state |= state; } else if (strcmp(*argv, "proxy") == 0) ndm.ndm_flags = NTF_PROXY; else { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) filter.family = filter.pfx.family; } argc--; argv++; } ll_init_map(&rth); if (filter_dev) { if ((filter.index = ll_name_to_index(filter_dev)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", filter_dev); return -1; } } if (flush) { int round = 0; char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.state &= ~NUD_FAILED; while (round < MAX_ROUNDS) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNEIGH) < 0) { perror("Cannot send dump request"); exit(1); } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_neigh, stdout) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (filter.flushed == 0) { if (show_stats) { if (round == 0) printf("Nothing to flush.\n"); else printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); } fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); if (show_stats) { printf("\n*** Round %d, deleting %d entries ***\n", round, filter.flushed); fflush(stdout); } } printf("*** Flush not complete bailing out after %d rounds\n", MAX_ROUNDS); return 1; } ndm.ndm_family = filter.family; if (rtnl_dump_request(&rth, RTM_GETNEIGH, &ndm, sizeof(struct ndmsg)) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, print_neigh, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; char mxbuf[256]; struct rtattr * mxrta = (void*)mxbuf; unsigned mxlock = 0; char *d = NULL; int gw_ok = 0; int dst_ok = 0; int proto_ok = 0; int type_ok = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.r.rtm_family = preferred_family; req.r.rtm_table = RT_TABLE_MAIN; req.r.rtm_scope = RT_SCOPE_NOWHERE; if (cmd != RTM_DELROUTE) { req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; } mxrta->rta_type = RTA_METRICS; mxrta->rta_len = RTA_LENGTH(0); while (argc > 0) { if (strcmp(*argv, "src") == 0) { inet_prefix addr; NEXT_ARG(); get_addr(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen); } else if (strcmp(*argv, "via") == 0) { inet_prefix addr; gw_ok = 1; NEXT_ARG(); get_addr(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen); } else if (strcmp(*argv, "mtu") == 0) { unsigned mtu; NEXT_ARG(); if (strcmp(*argv, "lock") == 0) { mxlock |= (1<<RTAX_MTU); NEXT_ARG(); } if (get_unsigned(&mtu, *argv, 0)) { invarg("\"mtu\" value is invalid\n", *argv); } rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); } else if (matches(*argv, "protocol") == 0) { int prot; NEXT_ARG(); if (rtnl_rtprot_a2n(&prot, *argv)) invarg("\"protocol\" value is invalid\n", *argv); req.r.rtm_protocol = prot; proto_ok =1; } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "oif") == 0) { NEXT_ARG(); d = *argv; } else { int type; inet_prefix dst; if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if ((**argv < '0' || **argv > '9') && rtnl_rtntype_a2n(&type, *argv) == 0) { NEXT_ARG(); req.r.rtm_type = type; type_ok = 1; } if (dst_ok) { duparg2("to", *argv); } get_prefix(&dst, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = dst.family; } req.r.rtm_dst_len = dst.bitlen; dst_ok = 1; if (dst.bytelen) { addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); } } argc--; argv++; } if (rtnl_open(&rth, 0) < 0) { exit(1); } if (d) { int idx; ll_init_map(&rth); if (d) { if ((idx = ll_name_to_index(d)) == 0) { bb_error_msg("Cannot find device \"%s\"", d); return -1; } addattr32(&req.n, sizeof(req), RTA_OIF, idx); } } if (mxrta->rta_len > RTA_LENGTH(0)) { if (mxlock) { rta_addattr32(mxrta, sizeof(mxbuf), RTAX_LOCK, mxlock); } addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); } if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = AF_INET; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { exit(2); } return 0; }
int ipaddr_list_or_flush(int argc, char **argv, int flush) { struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l; struct rtnl_handle rth; char *filter_dev = NULL; int no_link = 0; ipaddr_reset_filter(oneline); filter.showqueue = 1; if (filter.family == AF_UNSPEC) filter.family = preferred_family; if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); return -1; } if (filter.family == AF_PACKET) { fprintf(stderr, "Cannot flush link addresses.\n"); return -1; } } while (argc > 0) { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) filter.family = filter.pfx.family; } else if (strcmp(*argv, "scope") == 0) { int scope = 0; NEXT_ARG(); filter.scopemask = -1; if (rtnl_rtscope_a2n(&scope, *argv)) { if (strcmp(*argv, "all") != 0) invarg("invalid \"scope\"\n", *argv); scope = RT_SCOPE_NOWHERE; filter.scopemask = 0; } filter.scope = scope; } else if (strcmp(*argv, "up") == 0) { filter.up = 1; } else if (strcmp(*argv, "dynamic") == 0) { filter.flags &= ~IFA_F_PERMANENT; filter.flagmask |= IFA_F_PERMANENT; } else if (strcmp(*argv, "permanent") == 0) { filter.flags |= IFA_F_PERMANENT; filter.flagmask |= IFA_F_PERMANENT; } else if (strcmp(*argv, "secondary") == 0) { filter.flags |= IFA_F_SECONDARY; filter.flagmask |= IFA_F_SECONDARY; } else if (strcmp(*argv, "primary") == 0) { filter.flags &= ~IFA_F_SECONDARY; filter.flagmask |= IFA_F_SECONDARY; } else if (strcmp(*argv, "tentative") == 0) { filter.flags |= IFA_F_TENTATIVE; filter.flagmask |= IFA_F_TENTATIVE; } else if (strcmp(*argv, "deprecated") == 0) { filter.flags |= IFA_F_DEPRECATED; filter.flagmask |= IFA_F_DEPRECATED; } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); filter.label = *argv; } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (filter_dev) duparg2("dev", *argv); filter_dev = *argv; } argv++; argc--; } if (rtnl_open(&rth, 0) < 0) exit(1); if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } if (filter_dev) { filter.ifindex = ll_name_to_index(filter_dev); if (filter.ifindex <= 0) { fprintf(stderr, "Device \"%s\" does not exist.\n", filter_dev); return -1; } } if (flush) { int round = 0; char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); exit(1); } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (filter.flushed == 0) { if (round == 0) { fprintf(stderr, "Nothing to flush.\n"); } else if (show_stats) printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); if (show_stats) { printf("\n*** Round %d, deleting %d addresses ***\n", round, filter.flushed); fflush(stdout); } } } if (filter.family != AF_PACKET) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } if (filter.family && filter.family != AF_PACKET) { struct nlmsg_list **lp; lp=&linfo; if (filter.oneline) no_link = 1; while ((l=*lp)!=NULL) { int ok = 0; struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a=ainfo; a; a=a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); if (ifa->ifa_index != ifi->ifi_index || (filter.family && filter.family != ifa->ifa_family)) continue; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) continue; if ((filter.flags^ifa->ifa_flags)&filter.flagmask) continue; if (filter.pfx.family || filter.label) { struct rtattr *tb[IFA_MAX+1]; parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (filter.pfx.family && tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) continue; } if (filter.label) { SPRINT_BUF(b1); const char *label; if (tb[IFA_LABEL]) label = RTA_DATA(tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) continue; } } ok = 1; break; } if (!ok) *lp = l->next; else lp = &l->next; } } for (l=linfo; l; l = l->next) { if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { struct ifinfomsg *ifi = NLMSG_DATA(&l->h); if (filter.family != AF_PACKET) print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); } fflush(stdout); } exit(0); }
static int iproute_list_or_flush(int argc, char **argv, int flush) { int do_ipv6 = preferred_family; struct rtnl_handle rth; char *id = NULL; char *od = NULL; iproute_reset_filter(); filter.tb = RT_TABLE_MAIN; if (flush && argc <= 0) { fprintf(stderr, "\"ip route flush\" requires arguments.\n"); return -1; } while (argc > 0) { if (matches(*argv, "protocol") == 0) { int prot = 0; NEXT_ARG(); filter.protocolmask = -1; if (rtnl_rtprot_a2n(&prot, *argv)) { if (strcmp(*argv, "all") != 0) { invarg("invalid \"protocol\"\n", *argv); } prot = 0; filter.protocolmask = 0; } filter.protocol = prot; } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "oif") == 0) { NEXT_ARG(); od = *argv; } else if (strcmp(*argv, "iif") == 0) { NEXT_ARG(); id = *argv; } else if (matches(*argv, "from") == 0) { NEXT_ARG(); if (matches(*argv, "root") == 0) { NEXT_ARG(); get_prefix(&filter.rsrc, *argv, do_ipv6); } else if (matches(*argv, "match") == 0) { NEXT_ARG(); get_prefix(&filter.msrc, *argv, do_ipv6); } else { if (matches(*argv, "exact") == 0) { NEXT_ARG(); } get_prefix(&filter.msrc, *argv, do_ipv6); filter.rsrc = filter.msrc; } } else { if (matches(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "root") == 0) { NEXT_ARG(); get_prefix(&filter.rdst, *argv, do_ipv6); } else if (matches(*argv, "match") == 0) { NEXT_ARG(); get_prefix(&filter.mdst, *argv, do_ipv6); } else { if (matches(*argv, "exact") == 0) { NEXT_ARG(); } get_prefix(&filter.mdst, *argv, do_ipv6); filter.rdst = filter.mdst; } } argc--; argv++; } if (do_ipv6 == AF_UNSPEC && filter.tb) { do_ipv6 = AF_INET; } if (rtnl_open(&rth, 0) < 0) { exit(1); } ll_init_map(&rth); if (id || od) { int idx; if (id) { if ((idx = ll_name_to_index(id)) == 0) { bb_error_msg("Cannot find device \"%s\"", id); return -1; } filter.iif = idx; filter.iifmask = -1; } if (od) { if ((idx = ll_name_to_index(od)) == 0) { bb_error_msg("Cannot find device \"%s\"", od); } filter.oif = idx; filter.oifmask = -1; } } if (flush) { int round = 0; char flushb[4096-512]; if (filter.tb == -1) { if (do_ipv6 != AF_INET6) iproute_flush_cache(); if (do_ipv6 == AF_INET) return 0; } filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { perror("Cannot send dump request"); return -1; } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) { bb_error_msg("Flush terminated\n"); return -1; } if (filter.flushed == 0) { if (round == 0) { if (filter.tb != -1 || do_ipv6 == AF_INET6) fprintf(stderr, "Nothing to flush.\n"); } fflush(stdout); return 0; } round++; if (flush_update() < 0) exit(1); } } if (filter.tb != -1) { if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { bb_perror_msg_and_die("Cannot send dump request"); } } else { if (rtnl_rtcache_request(&rth, do_ipv6) < 0) { bb_perror_msg_and_die("Cannot send dump request"); } } if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) { bb_error_msg_and_die("Dump terminated"); } exit(0); }
int ipaddr_list_or_flush(int argc, char **argv, int flush) { static const char *const option[] = { "to", "scope", "up", "label", "dev", 0 }; struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l; struct rtnl_handle rth; char *filter_dev = NULL; int no_link = 0; ipaddr_reset_filter(oneline); filter.showqueue = 1; if (filter.family == AF_UNSPEC) filter.family = preferred_family; if (flush) { if (argc <= 0) { bb_error_msg(bb_msg_requires_arg, "flush"); return -1; } if (filter.family == AF_PACKET) { bb_error_msg("cannot flush link addresses"); return -1; } } while (argc > 0) { const int option_num = index_in_str_array(option, *argv); switch (option_num) { case 0: /* to */ NEXT_ARG(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) { filter.family = filter.pfx.family; } break; case 1: /* scope */ { uint32_t scope = 0; NEXT_ARG(); filter.scopemask = -1; if (rtnl_rtscope_a2n(&scope, *argv)) { if (strcmp(*argv, "all") != 0) { invarg(*argv, "scope"); } scope = RT_SCOPE_NOWHERE; filter.scopemask = 0; } filter.scope = scope; break; } case 2: /* up */ filter.up = 1; break; case 3: /* label */ NEXT_ARG(); filter.label = *argv; break; case 4: /* dev */ NEXT_ARG(); default: if (filter_dev) { duparg2("dev", *argv); } filter_dev = *argv; } argv++; argc--; } if (rtnl_open(&rth, 0) < 0) exit(1); if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { bb_perror_msg_and_die("cannot send dump request"); } if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) { bb_error_msg_and_die("dump terminated"); } if (filter_dev) { filter.ifindex = ll_name_to_index(filter_dev); if (filter.ifindex <= 0) { bb_error_msg("device \"%s\" does not exist", filter_dev); return -1; } } if (flush) { char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); exit(1); } filter.flushed = 0; if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) { fprintf(stderr, "Flush terminated\n"); exit(1); } if (filter.flushed == 0) { fflush(stdout); return 0; } if (flush_update() < 0) exit(1); } } if (filter.family != AF_PACKET) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { bb_perror_msg_and_die("cannot send dump request"); } if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) { bb_error_msg_and_die("dump terminated"); } } if (filter.family && filter.family != AF_PACKET) { struct nlmsg_list **lp; lp=&linfo; if (filter.oneline) no_link = 1; while ((l=*lp)!=NULL) { int ok = 0; struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a=ainfo; a; a=a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); if (ifa->ifa_index != ifi->ifi_index || (filter.family && filter.family != ifa->ifa_family)) continue; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) continue; if ((filter.flags^ifa->ifa_flags)&filter.flagmask) continue; if (filter.pfx.family || filter.label) { struct rtattr *tb[IFA_MAX+1]; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (filter.pfx.family && tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) continue; } if (filter.label) { SPRINT_BUF(b1); const char *label; if (tb[IFA_LABEL]) label = RTA_DATA(tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) continue; } } ok = 1; break; } if (!ok) *lp = l->next; else lp = &l->next; } } for (l=linfo; l; l = l->next) { if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { struct ifinfomsg *ifi = NLMSG_DATA(&l->h); if (filter.family != AF_PACKET) print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); } fflush(stdout); } exit(0); }
static int iproute_get(int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; char *idev = NULL; char *odev = NULL; int connected = 0; int from_ok = 0; const char *options[] = { "from", "iif", "oif", "dev", "notify", "connected", "to", 0 }; memset(&req, 0, sizeof(req)); iproute_reset_filter(); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETROUTE; req.r.rtm_family = preferred_family; req.r.rtm_table = 0; req.r.rtm_protocol = 0; req.r.rtm_scope = 0; req.r.rtm_type = 0; req.r.rtm_src_len = 0; req.r.rtm_dst_len = 0; req.r.rtm_tos = 0; while (argc > 0) { switch (compare_string_array(options, *argv)) { case 0: /* from */ { inet_prefix addr; NEXT_ARG(); from_ok = 1; get_prefix(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } if (addr.bytelen) { addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); } req.r.rtm_src_len = addr.bitlen; break; } case 1: /* iif */ NEXT_ARG(); idev = *argv; break; case 2: /* oif */ case 3: /* dev */ NEXT_ARG(); odev = *argv; break; case 4: /* notify */ req.r.rtm_flags |= RTM_F_NOTIFY; break; case 5: /* connected */ connected = 1; break; case 6: /* to */ NEXT_ARG(); default: { inet_prefix addr; get_prefix(&addr, *argv, req.r.rtm_family); if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = addr.family; } if (addr.bytelen) { addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen); } req.r.rtm_dst_len = addr.bitlen; } argc--; argv++; } } if (req.r.rtm_dst_len == 0) { bb_error_msg_and_die("need at least destination address"); } if (rtnl_open(&rth, 0) < 0) exit(1); ll_init_map(&rth); if (idev || odev) { int idx; if (idev) { if ((idx = ll_name_to_index(idev)) == 0) { bb_error_msg("Cannot find device \"%s\"", idev); return -1; } addattr32(&req.n, sizeof(req), RTA_IIF, idx); } if (odev) { if ((idx = ll_name_to_index(odev)) == 0) { bb_error_msg("Cannot find device \"%s\"", odev); return -1; } addattr32(&req.n, sizeof(req), RTA_OIF, idx); } } if (req.r.rtm_family == AF_UNSPEC) { req.r.rtm_family = AF_INET; } if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) { exit(2); } if (connected && !from_ok) { struct rtmsg *r = NLMSG_DATA(&req.n); int len = req.n.nlmsg_len; struct rtattr * tb[RTA_MAX+1]; if (print_route(NULL, &req.n, (void*)stdout) < 0) { bb_error_msg_and_die("An error :-)"); } if (req.n.nlmsg_type != RTM_NEWROUTE) { bb_error_msg("Not a route?"); return -1; } len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) { bb_error_msg("Wrong len %d", len); return -1; } memset(tb, 0, sizeof(tb)); parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); if (tb[RTA_PREFSRC]) { tb[RTA_PREFSRC]->rta_type = RTA_SRC; r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]); } else if (!tb[RTA_SRC]) { bb_error_msg("Failed to connect the route"); return -1; } if (!odev && tb[RTA_OIF]) { tb[RTA_OIF]->rta_type = 0; } if (tb[RTA_GATEWAY]) { tb[RTA_GATEWAY]->rta_type = 0; } if (!idev && tb[RTA_IIF]) { tb[RTA_IIF]->rta_type = 0; } req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETROUTE; if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) { exit(2); } } if (print_route(NULL, &req.n, (void*)stdout) < 0) { bb_error_msg_and_die("An error :-)"); } exit(0); }
static int ipaddrlabel_modify(int cmd, int argc, char **argv) { struct { struct nlmsghdr n; struct ifaddrlblmsg ifal; char buf[1024]; } req; inet_prefix prefix; uint32_t label = 0xffffffffUL; char *p = NULL; char *l = NULL; memset(&req, 0, sizeof(req)); memset(&prefix, 0, sizeof(prefix)); req.n.nlmsg_type = cmd; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.ifal.ifal_family = preferred_family; req.ifal.ifal_prefixlen = 0; req.ifal.ifal_index = 0; if (cmd == RTM_NEWADDRLABEL) { req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; } while (argc > 0) { if (strcmp(*argv, "prefix") == 0) { NEXT_ARG(); p = *argv; get_prefix(&prefix, *argv, preferred_family); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if ((req.ifal.ifal_index = ll_name_to_index(*argv)) == 0) invarg("dev is invalid\n", *argv); } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); l = *argv; if (get_u32(&label, *argv, 0) || label == 0xffffffffUL) invarg("label is invalid\n", *argv); } argc--; argv++; } if (p == NULL) { fprintf(stderr, "Not enough information: \"prefix\" argument is required.\n"); return -1; } if (l == NULL) { fprintf(stderr, "Not enough information: \"label\" argument is required.\n"); return -1; } addattr32(&req.n, sizeof(req), IFAL_LABEL, label); addattr_l(&req.n, sizeof(req), IFAL_ADDRESS, &prefix.data, prefix.bytelen); req.ifal.ifal_prefixlen = prefix.bitlen; if (req.ifal.ifal_family == AF_UNSPEC) req.ifal.ifal_family = AF_INET6; if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; return 0; }
static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct xfrm_usersa_info xsinfo; char buf[RTA_BUF_SIZE]; } req; struct xfrm_replay_state replay; char *idp = NULL; char *aeadop = NULL; char *ealgop = NULL; char *aalgop = NULL; char *calgop = NULL; char *coap = NULL; char *sctxp = NULL; __u32 extra_flags = 0; struct xfrm_mark mark = {0, 0}; struct { struct xfrm_user_sec_ctx sctx; char str[CTX_BUF_SIZE]; } ctx; memset(&req, 0, sizeof(req)); memset(&replay, 0, sizeof(replay)); memset(&ctx, 0, sizeof(ctx)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.xsinfo.family = preferred_family; req.xsinfo.lft.soft_byte_limit = XFRM_INF; req.xsinfo.lft.hard_byte_limit = XFRM_INF; req.xsinfo.lft.soft_packet_limit = XFRM_INF; req.xsinfo.lft.hard_packet_limit = XFRM_INF; while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); xfrm_mode_parse(&req.xsinfo.mode, &argc, &argv); } else if (strcmp(*argv, "mark") == 0) { xfrm_parse_mark(&mark, &argc, &argv); } else if (strcmp(*argv, "reqid") == 0) { NEXT_ARG(); xfrm_reqid_parse(&req.xsinfo.reqid, &argc, &argv); } else if (strcmp(*argv, "seq") == 0) { NEXT_ARG(); xfrm_seq_parse(&req.xsinfo.seq, &argc, &argv); } else if (strcmp(*argv, "replay-window") == 0) { NEXT_ARG(); if (get_u8(&req.xsinfo.replay_window, *argv, 0)) invarg("value after \"replay-window\" is invalid", *argv); } else if (strcmp(*argv, "replay-seq") == 0) { NEXT_ARG(); if (get_u32(&replay.seq, *argv, 0)) invarg("value after \"replay-seq\" is invalid", *argv); } else if (strcmp(*argv, "replay-oseq") == 0) { NEXT_ARG(); if (get_u32(&replay.oseq, *argv, 0)) invarg("value after \"replay-oseq\" is invalid", *argv); } else if (strcmp(*argv, "flag") == 0) { NEXT_ARG(); xfrm_state_flag_parse(&req.xsinfo.flags, &argc, &argv); } else if (strcmp(*argv, "extra-flag") == 0) { NEXT_ARG(); xfrm_state_extra_flag_parse(&extra_flags, &argc, &argv); } else if (strcmp(*argv, "sel") == 0) { NEXT_ARG(); preferred_family = AF_UNSPEC; xfrm_selector_parse(&req.xsinfo.sel, &argc, &argv); preferred_family = req.xsinfo.sel.family; } else if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); xfrm_lifetime_cfg_parse(&req.xsinfo.lft, &argc, &argv); } else if (strcmp(*argv, "encap") == 0) { struct xfrm_encap_tmpl encap; inet_prefix oa; NEXT_ARG(); xfrm_encap_type_parse(&encap.encap_type, &argc, &argv); NEXT_ARG(); if (get_u16(&encap.encap_sport, *argv, 0)) invarg("SPORT value after \"encap\" is invalid", *argv); encap.encap_sport = htons(encap.encap_sport); NEXT_ARG(); if (get_u16(&encap.encap_dport, *argv, 0)) invarg("DPORT value after \"encap\" is invalid", *argv); encap.encap_dport = htons(encap.encap_dport); NEXT_ARG(); get_addr(&oa, *argv, AF_UNSPEC); memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa)); addattr_l(&req.n, sizeof(req.buf), XFRMA_ENCAP, (void *)&encap, sizeof(encap)); } else if (strcmp(*argv, "coa") == 0) { inet_prefix coa; xfrm_address_t xcoa; if (coap) duparg("coa", *argv); coap = *argv; NEXT_ARG(); get_prefix(&coa, *argv, preferred_family); if (coa.family == AF_UNSPEC) invarg("value after \"coa\" has an unrecognized address family", *argv); if (coa.bytelen > sizeof(xcoa)) invarg("value after \"coa\" is too large", *argv); memset(&xcoa, 0, sizeof(xcoa)); memcpy(&xcoa, &coa.data, coa.bytelen); addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR, (void *)&xcoa, sizeof(xcoa)); } else if (strcmp(*argv, "ctx") == 0) { char *context; if (sctxp) duparg("ctx", *argv); sctxp = *argv; NEXT_ARG(); context = *argv; xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx); addattr_l(&req.n, sizeof(req.buf), XFRMA_SEC_CTX, (void *)&ctx, ctx.sctx.len); } else { /* try to assume ALGO */ int type = xfrm_algotype_getbyname(*argv); switch (type) { case XFRMA_ALG_AEAD: case XFRMA_ALG_CRYPT: case XFRMA_ALG_AUTH: case XFRMA_ALG_AUTH_TRUNC: case XFRMA_ALG_COMP: { /* ALGO */ struct { union { struct xfrm_algo alg; struct xfrm_algo_aead aead; struct xfrm_algo_auth auth; } u; char buf[XFRM_ALGO_KEY_BUF_SIZE]; } alg = {}; int len; __u32 icvlen, trunclen; char *name; char *key = ""; char *buf; switch (type) { case XFRMA_ALG_AEAD: if (ealgop || aalgop || aeadop) duparg("ALGO-TYPE", *argv); aeadop = *argv; break; case XFRMA_ALG_CRYPT: if (ealgop || aeadop) duparg("ALGO-TYPE", *argv); ealgop = *argv; break; case XFRMA_ALG_AUTH: case XFRMA_ALG_AUTH_TRUNC: if (aalgop || aeadop) duparg("ALGO-TYPE", *argv); aalgop = *argv; break; case XFRMA_ALG_COMP: if (calgop) duparg("ALGO-TYPE", *argv); calgop = *argv; break; default: /* not reached */ invarg("ALGO-TYPE value is invalid\n", *argv); } if (!NEXT_ARG_OK()) missarg("ALGO-NAME"); NEXT_ARG(); name = *argv; switch (type) { case XFRMA_ALG_AEAD: case XFRMA_ALG_CRYPT: case XFRMA_ALG_AUTH: case XFRMA_ALG_AUTH_TRUNC: if (!NEXT_ARG_OK()) missarg("ALGO-KEYMAT"); NEXT_ARG(); key = *argv; break; } buf = alg.u.alg.alg_key; len = sizeof(alg.u.alg); switch (type) { case XFRMA_ALG_AEAD: if (!NEXT_ARG_OK()) missarg("ALGO-ICV-LEN"); NEXT_ARG(); if (get_u32(&icvlen, *argv, 0)) invarg("ALGO-ICV-LEN value is invalid", *argv); alg.u.aead.alg_icv_len = icvlen; buf = alg.u.aead.alg_key; len = sizeof(alg.u.aead); break; case XFRMA_ALG_AUTH_TRUNC: if (!NEXT_ARG_OK()) missarg("ALGO-TRUNC-LEN"); NEXT_ARG(); if (get_u32(&trunclen, *argv, 0)) invarg("ALGO-TRUNC-LEN value is invalid", *argv); alg.u.auth.alg_trunc_len = trunclen; buf = alg.u.auth.alg_key; len = sizeof(alg.u.auth); break; } xfrm_algo_parse((void *)&alg, type, name, key, buf, sizeof(alg.buf)); len += alg.u.alg.alg_key_len; addattr_l(&req.n, sizeof(req.buf), type, (void *)&alg, len); break; } default: /* try to assume ID */ if (idp) invarg("unknown", *argv); idp = *argv; /* ID */ xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id, &req.xsinfo.family, 0, &argc, &argv); if (preferred_family == AF_UNSPEC) preferred_family = req.xsinfo.family; } } argc--; argv++; } if (replay.seq || replay.oseq) addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_VAL, (void *)&replay, sizeof(replay)); if (extra_flags) addattr32(&req.n, sizeof(req.buf), XFRMA_SA_EXTRA_FLAGS, extra_flags); if (!idp) { fprintf(stderr, "Not enough information: ID is required\n"); exit(1); } if (mark.m) { int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK, (void *)&mark, sizeof(mark)); if (r < 0) { fprintf(stderr, "XFRMA_MARK failed\n"); exit(1); } } if (xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) { switch (req.xsinfo.mode) { case XFRM_MODE_TRANSPORT: case XFRM_MODE_TUNNEL: break; case XFRM_MODE_BEET: if (req.xsinfo.id.proto == IPPROTO_ESP) break; default: fprintf(stderr, "MODE value is invalid with XFRM-PROTO value \"%s\"\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } switch (req.xsinfo.id.proto) { case IPPROTO_ESP: if (calgop) { fprintf(stderr, "ALGO-TYPE value \"%s\" is invalid with XFRM-PROTO value \"%s\"\n", strxf_algotype(XFRMA_ALG_COMP), strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } if (!ealgop && !aeadop) { fprintf(stderr, "ALGO-TYPE value \"%s\" or \"%s\" is required with XFRM-PROTO value \"%s\"\n", strxf_algotype(XFRMA_ALG_CRYPT), strxf_algotype(XFRMA_ALG_AEAD), strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } break; case IPPROTO_AH: if (ealgop || aeadop || calgop) { fprintf(stderr, "ALGO-TYPE values \"%s\", \"%s\", and \"%s\" are invalid with XFRM-PROTO value \"%s\"\n", strxf_algotype(XFRMA_ALG_CRYPT), strxf_algotype(XFRMA_ALG_AEAD), strxf_algotype(XFRMA_ALG_COMP), strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } if (!aalgop) { fprintf(stderr, "ALGO-TYPE value \"%s\" or \"%s\" is required with XFRM-PROTO value \"%s\"\n", strxf_algotype(XFRMA_ALG_AUTH), strxf_algotype(XFRMA_ALG_AUTH_TRUNC), strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } break; case IPPROTO_COMP: if (ealgop || aalgop || aeadop) { fprintf(stderr, "ALGO-TYPE values \"%s\", \"%s\", \"%s\", and \"%s\" are invalid with XFRM-PROTO value \"%s\"\n", strxf_algotype(XFRMA_ALG_CRYPT), strxf_algotype(XFRMA_ALG_AUTH), strxf_algotype(XFRMA_ALG_AUTH_TRUNC), strxf_algotype(XFRMA_ALG_AEAD), strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } if (!calgop) { fprintf(stderr, "ALGO-TYPE value \"%s\" is required with XFRM-PROTO value \"%s\"\n", strxf_algotype(XFRMA_ALG_COMP), strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } break; } } else { if (ealgop || aalgop || aeadop || calgop) { fprintf(stderr, "ALGO is invalid with XFRM-PROTO value \"%s\"\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } } if (xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) { switch (req.xsinfo.mode) { case XFRM_MODE_ROUTEOPTIMIZATION: case XFRM_MODE_IN_TRIGGER: break; case 0: fprintf(stderr, "\"mode\" is required with XFRM-PROTO value \"%s\"\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); default: fprintf(stderr, "MODE value is invalid with XFRM-PROTO value \"%s\"\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } if (!coap) { fprintf(stderr, "\"coa\" is required with XFRM-PROTO value \"%s\"\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } } else { if (coap) { fprintf(stderr, "\"coa\" is invalid with XFRM-PROTO value \"%s\"\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (req.xsinfo.family == AF_UNSPEC) req.xsinfo.family = AF_INET; if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) exit(2); rtnl_close(&rth); return 0; }
int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family, int loose, int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; inet_prefix dst; inet_prefix src; memset(&dst, 0, sizeof(dst)); memset(&src, 0, sizeof(src)); while (1) { if (strcmp(*argv, "src") == 0) { NEXT_ARG(); get_prefix(&src, *argv, preferred_family); if (src.family == AF_UNSPEC) invarg("\"src\" address family is AF_UNSPEC", *argv); if (family) *family = src.family; memcpy(saddr, &src.data, sizeof(*saddr)); filter.id_src_mask = src.bitlen; } else if (strcmp(*argv, "dst") == 0) { NEXT_ARG(); get_prefix(&dst, *argv, preferred_family); if (dst.family == AF_UNSPEC) invarg("\"dst\" address family is AF_UNSPEC", *argv); if (family) *family = dst.family; memcpy(&id->daddr, &dst.data, sizeof(id->daddr)); filter.id_dst_mask = dst.bitlen; } else if (strcmp(*argv, "proto") == 0) { int ret; NEXT_ARG(); ret = xfrm_xfrmproto_getbyname(*argv); if (ret < 0) invarg("\"XFRM_PROTO\" is invalid", *argv); id->proto = (__u8)ret; filter.id_proto_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "spi") == 0) { __u32 spi; NEXT_ARG(); if (get_u32(&spi, *argv, 0)) invarg("\"SPI\" is invalid", *argv); spi = htonl(spi); id->spi = spi; filter.id_spi_mask = XFRM_FILTER_MASK_FULL; } else { PREV_ARG(); /* back track */ break; } if (!NEXT_ARG_OK()) break; NEXT_ARG(); } if (src.family && dst.family && (src.family != dst.family)) invarg("the same address family is required between \"src\" and \"dst\"", *argv); if (loose == 0 && id->proto == 0) missarg("XFRM_PROTO"); if (argc == *argcp) missarg("ID"); *argcp = argc; *argvp = argv; return 0; }
static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct xfrm_usersa_info xsinfo; char buf[RTA_BUF_SIZE]; } req; char *idp = NULL; char *ealgop = NULL; char *aalgop = NULL; char *calgop = NULL; char *coap = NULL; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.xsinfo.family = preferred_family; req.xsinfo.lft.soft_byte_limit = XFRM_INF; req.xsinfo.lft.hard_byte_limit = XFRM_INF; req.xsinfo.lft.soft_packet_limit = XFRM_INF; req.xsinfo.lft.hard_packet_limit = XFRM_INF; while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); xfrm_mode_parse(&req.xsinfo.mode, &argc, &argv); } else if (strcmp(*argv, "reqid") == 0) { NEXT_ARG(); xfrm_reqid_parse(&req.xsinfo.reqid, &argc, &argv); } else if (strcmp(*argv, "seq") == 0) { NEXT_ARG(); xfrm_seq_parse(&req.xsinfo.seq, &argc, &argv); } else if (strcmp(*argv, "replay-window") == 0) { NEXT_ARG(); if (get_u8(&req.xsinfo.replay_window, *argv, 0)) invarg("\"replay-window\" value is invalid", *argv); } else if (strcmp(*argv, "flag") == 0) { NEXT_ARG(); xfrm_state_flag_parse(&req.xsinfo.flags, &argc, &argv); } else if (strcmp(*argv, "sel") == 0) { NEXT_ARG(); xfrm_selector_parse(&req.xsinfo.sel, &argc, &argv); } else if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); xfrm_lifetime_cfg_parse(&req.xsinfo.lft, &argc, &argv); } else if (strcmp(*argv, "encap") == 0) { struct xfrm_encap_tmpl encap; inet_prefix oa; NEXT_ARG(); xfrm_encap_type_parse(&encap.encap_type, &argc, &argv); NEXT_ARG(); if (get_u16(&encap.encap_sport, *argv, 0)) invarg("\"encap\" sport value is invalid", *argv); encap.encap_sport = htons(encap.encap_sport); NEXT_ARG(); if (get_u16(&encap.encap_dport, *argv, 0)) invarg("\"encap\" dport value is invalid", *argv); encap.encap_dport = htons(encap.encap_dport); NEXT_ARG(); get_addr(&oa, *argv, AF_UNSPEC); memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa)); addattr_l(&req.n, sizeof(req.buf), XFRMA_ENCAP, (void *)&encap, sizeof(encap)); } else if (strcmp(*argv, "coa") == 0) { inet_prefix coa; xfrm_address_t xcoa; if (coap) duparg("coa", *argv); coap = *argv; NEXT_ARG(); get_prefix(&coa, *argv, preferred_family); if (coa.family == AF_UNSPEC) invarg("\"coa\" address family is AF_UNSPEC", *argv); if (coa.bytelen > sizeof(xcoa)) invarg("\"coa\" address length is too large", *argv); memset(&xcoa, 0, sizeof(xcoa)); memcpy(&xcoa, &coa.data, coa.bytelen); addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR, (void *)&xcoa, sizeof(xcoa)); } else { /* try to assume ALGO */ int type = xfrm_algotype_getbyname(*argv); switch (type) { case XFRMA_ALG_CRYPT: case XFRMA_ALG_AUTH: case XFRMA_ALG_COMP: { /* ALGO */ struct { struct xfrm_algo alg; char buf[XFRM_ALGO_KEY_BUF_SIZE]; } alg; int len; char *name; char *key; switch (type) { case XFRMA_ALG_CRYPT: if (ealgop) duparg("ALGOTYPE", *argv); ealgop = *argv; break; case XFRMA_ALG_AUTH: if (aalgop) duparg("ALGOTYPE", *argv); aalgop = *argv; break; case XFRMA_ALG_COMP: if (calgop) duparg("ALGOTYPE", *argv); calgop = *argv; break; default: /* not reached */ invarg("\"ALGOTYPE\" is invalid\n", *argv); } if (!NEXT_ARG_OK()) missarg("ALGONAME"); NEXT_ARG(); name = *argv; if (!NEXT_ARG_OK()) missarg("ALGOKEY"); NEXT_ARG(); key = *argv; memset(&alg, 0, sizeof(alg)); xfrm_algo_parse((void *)&alg, type, name, key, sizeof(alg.buf)); len = sizeof(struct xfrm_algo) + alg.alg.alg_key_len; addattr_l(&req.n, sizeof(req.buf), type, (void *)&alg, len); break; } default: /* try to assume ID */ if (idp) invarg("unknown", *argv); idp = *argv; /* ID */ xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id, &req.xsinfo.family, 0, &argc, &argv); if (preferred_family == AF_UNSPEC) preferred_family = req.xsinfo.family; } } argc--; argv++; } if (!idp) { fprintf(stderr, "Not enough information: \"ID\" is required\n"); exit(1); } switch (req.xsinfo.mode) { case XFRM_MODE_TRANSPORT: case XFRM_MODE_TUNNEL: if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) { fprintf(stderr, "\"mode\" is invalid with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } break; case XFRM_MODE_ROUTEOPTIMIZATION: case XFRM_MODE_IN_TRIGGER: if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) { fprintf(stderr, "\"mode\" is invalid with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } if (req.xsinfo.id.spi != 0) { fprintf(stderr, "\"spi\" must be 0 with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } break; default: break; } if (ealgop || aalgop || calgop) { if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) { fprintf(stderr, "\"ALGO\" is invalid with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } } else { if (xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) { fprintf(stderr, "\"ALGO\" is required with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit (1); } } if (coap) { if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) { fprintf(stderr, "\"coa\" is invalid with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit(1); } } else { if (xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) { fprintf(stderr, "\"coa\" is required with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto)); exit (1); } } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (req.xsinfo.family == AF_UNSPEC) req.xsinfo.family = AF_INET; if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); rtnl_close(&rth); return 0; }
int d2ladder_print_XML(std::FILE *ladderstrm) { // modified version of d2ladder_print - changes done by jfro with a little help of aaron t_d2ladder * d2ladder; t_d2ladder_info * ldata; int overalltype,classtype; unsigned int i,type; char laddermode[4][20]={"Hardcore", "Standard","Expansion HC","Expansion" }; char charclass[11][12]={"OverAll", "Amazon", "Sorceress", "Necromancer", "Paladin",\ "Barbarian", "Druid", "Assassin", "","",""} ; std::fprintf(ladderstrm,"<?xml version=\"1.0\"?>\n<D2_ladders>\n"); for(type=0; type <d2ladder_maxtype; type++) { d2ladder=d2ladderlist_find_type(type); if (!d2ladder) continue; if(d2ladder->len<=0) continue; ldata=d2ladder->info; overalltype=0; classtype=0; if(type<= D2LADDER_HC_OVERALL+D2CHAR_CLASS_MAX +1) { overalltype=0 ; classtype=type-D2LADDER_HC_OVERALL; } else if(type >= D2LADDER_STD_OVERALL && type<= D2LADDER_STD_OVERALL+D2CHAR_CLASS_MAX +1) { overalltype=1; classtype=type-D2LADDER_STD_OVERALL; } else if(type >= D2LADDER_EXP_HC_OVERALL && type<= D2LADDER_EXP_HC_OVERALL+D2CHAR_EXP_CLASS_MAX +1) { overalltype=2; classtype=type-D2LADDER_EXP_HC_OVERALL; } else if(type >= D2LADDER_EXP_STD_OVERALL && type<= D2LADDER_EXP_STD_OVERALL+D2CHAR_EXP_CLASS_MAX +1) { overalltype=3; classtype=type-D2LADDER_EXP_STD_OVERALL ; } std::fprintf(ladderstrm,"<ladder>\n\t<type>%d</type>\n\t<mode>%s</mode>\n\t<class>%s</class>\n", type,laddermode[overalltype],charclass[classtype]); for(i=0; i<d2ladder->len; i++) { if ((ldata[i].charname != NULL) && (ldata[i].charname[0] != '\0')) { std::fprintf(ladderstrm,"\t<char>\n\t\t<rank>%2d</rank>\n\t\t<name>%s</name>\n\t\t<level>%2d</level>\n", i+1,ldata[i].charname,ldata[i].level); std::fprintf(ladderstrm,"\t\t<experience>%u</experience>\n\t\t<class>%s</class>\n", ldata[i].experience,charclass[ldata[i].chclass+1]); std::fprintf(ladderstrm,"\t\t<prefix>%s</prefix>\n", get_prefix(overalltype,ldata[i].status,ldata[i].chclass+1)); if (((ldata[i].status) & (D2CHARINFO_STATUS_FLAG_DEAD | D2CHARINFO_STATUS_FLAG_HARDCORE)) == (D2CHARINFO_STATUS_FLAG_DEAD | D2CHARINFO_STATUS_FLAG_HARDCORE)) std::fprintf(ladderstrm,"\t\t<status>dead</status>\n\t</char>\n"); else std::fprintf(ladderstrm,"\t\t<status>alive</status>\n\t</char>\n"); } } std::fprintf(ladderstrm,"</ladder>\n"); std::fflush(ladderstrm); } std::fprintf(ladderstrm,"</D2_ladders>\n"); return 0; }
static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs) { ssize_t size, vsize; char *xattr_names, *p; int i; struct xattr_list *xattr_list = NULL; #if 0 while(1) { size = llistxattr(filename, NULL, 0); if(size <= 0) { if(size < 0 && errno != ENOTSUP) ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } xattr_names = malloc(size); if(xattr_names == NULL) { ERROR("Out of memory in read_attrs\n"); return 0; } size = llistxattr(filename, xattr_names, size); if(size < 0) { free(xattr_names); if(errno == ERANGE) /* xattr list grew? Try again */ continue; else { ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } } break; } #else ERROR("llistxattr not available"); #endif for(i = 0, p = xattr_names; p < xattr_names + size; i++) { struct xattr_list *x = realloc(xattr_list, (i + 1) * sizeof(struct xattr_list)); if(x == NULL) { ERROR("Out of memory in read_attrs\n"); goto failed; } else xattr_list = x; xattr_list[i].type = get_prefix(&xattr_list[i], p); p += strlen(p) + 1; if(xattr_list[i].type == -1) { ERROR("Unrecognised xattr prefix %s\n", xattr_list[i].full_name); free(xattr_list[i].full_name); i--; continue; } #if 0 while(1) { vsize = lgetxattr(filename, xattr_list[i].full_name, NULL, 0); if(vsize < 0) { ERROR("lgetxattr failed for %s in read_attrs," " because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } xattr_list[i].value = malloc(vsize); if(xattr_list[i].value == NULL) { ERROR("Out of memory in read_attrs\n"); free(xattr_list[i].full_name); goto failed; } vsize = lgetxattr(filename, xattr_list[i].full_name, xattr_list[i].value, vsize); if(vsize < 0) { free(xattr_list[i].value); if(errno == ERANGE) /* xattr grew? Try again */ continue; else { ERROR("lgetxattr failed for %s in " "read_attrs, because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } } break; } #else ERROR("lgetxattr not supported"); #endif xattr_list[i].vsize = vsize; TRACE("read_xattrs_from_system: filename %s, xattr name %s," " vsize %d\n", filename, xattr_list[i].full_name, xattr_list[i].vsize); } free(xattr_names); *xattrs = xattr_list; return i; failed: while(--i >= 0) { free(xattr_list[i].full_name); free(xattr_list[i].value); } free(xattr_list); free(xattr_names); return 0; }