| File: | netmask.c |
| Location: | line 414, column 34 |
| Description: | Use of memory after it is freed |
| 1 | /* netmask.c - a netmask generator | |||
| 2 | * | |||
| 3 | * Copyright (c) 1999 Robert Stone <talby@trap.mtview.ca.us>, | |||
| 4 | * Tom Lear <tom@trap.mtview.ca.us> | |||
| 5 | ||||
| 6 | This program is free software; you can redistribute it and/or modify | |||
| 7 | it under the terms of the GNU General Public License as published by | |||
| 8 | the Free Software Foundation; either version 2, or (at your option) | |||
| 9 | any later version. | |||
| 10 | ||||
| 11 | This program is distributed in the hope that it will be useful, | |||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| 14 | GNU General Public License for more details. | |||
| 15 | ||||
| 16 | You should have received a copy of the GNU General Public License | |||
| 17 | along with this program; if not, write to the Free Software | |||
| 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 19 | ||||
| 20 | #include <arpa/inet.h> | |||
| 21 | #include <getopt.h> | |||
| 22 | #include <netdb.h> | |||
| 23 | #include <netinet/in.h> | |||
| 24 | #include <stdio.h> | |||
| 25 | #include <stdlib.h> | |||
| 26 | #include <string.h> | |||
| 27 | #include <sys/socket.h> | |||
| 28 | #include <sys/types.h> | |||
| 29 | #include "errors.h" | |||
| 30 | ||||
| 31 | struct addrmask { | |||
| 32 | u_int32_t neta; | |||
| 33 | u_int32_t mask; | |||
| 34 | struct addrmask *next; | |||
| 35 | struct addrmask *prev; | |||
| 36 | }; | |||
| 37 | ||||
| 38 | struct option longopts[] = { | |||
| 39 | { "version", 0, 0, 'v' }, | |||
| 40 | { "help", 0, 0, 'h' }, | |||
| 41 | { "debug", 0, 0, 'd' }, | |||
| 42 | { "standard", 0, 0, 's' }, | |||
| 43 | { "cidr", 0, 0, 'c' }, | |||
| 44 | { "cisco", 0, 0, 'i' }, | |||
| 45 | { "range", 0, 0, 'r' }, | |||
| 46 | { "hex", 0, 0, 'x' }, | |||
| 47 | { "octal", 0, 0, 'o' }, | |||
| 48 | { "binary", 0, 0, 'b' }, | |||
| 49 | { "nodns", 0, 0, 'n' }, | |||
| 50 | { "max", 1, 0, 'M' }, | |||
| 51 | { "min", 1, 0, 'm' }, | |||
| 52 | { NULL((void*)0), 0, 0, 0 } | |||
| 53 | }; | |||
| 54 | ||||
| 55 | typedef enum { | |||
| 56 | OUT_STD, OUT_CIDR, OUT_CISCO, OUT_RANGE, OUT_HEX, OUT_OCTAL, OUT_BINARY | |||
| 57 | } output_t; | |||
| 58 | ||||
| 59 | int spectoaml(char *, int); | |||
| 60 | int display(output_t); | |||
| 61 | int addtoaml(u_int32_t addr, u_int32_t mask); | |||
| 62 | static u_int32_t mspectou32(char *); | |||
| 63 | ||||
| 64 | char version[] = "netmask, version "VERSION"2.3.7"; | |||
| 65 | char vversion[] = __DATE__"Feb 2 2014"" "__TIME__"20:03:45"; | |||
| 66 | char usage[] = "Try `%s --help' for more information.\n"; | |||
| 67 | char *progname = NULL((void*)0); | |||
| 68 | static struct addrmask *aml; | |||
| 69 | ||||
| 70 | int main(int argc, char *argv[]) { | |||
| 71 | int optc, h = 0, v = 0, debug = 0, dns = 1, lose = 0; | |||
| 72 | // u_int32_t min = ~0, max = 0; | |||
| 73 | output_t output = OUT_CIDR; | |||
| 74 | ||||
| 75 | progname = argv[0]; | |||
| 76 | initerrors(progname, 0, 0); /* stderr, nostatus */ | |||
| 77 | while((optc = getopt_long(argc, argv, "shoxdrvbincM:m:", longopts, | |||
| 78 | (int *) NULL((void*)0))) != EOF(-1)) switch(optc) { | |||
| 79 | case 'h': h = 1; break; | |||
| 80 | case 'v': v++; break; | |||
| 81 | case 'n': dns = 0; break; | |||
| 82 | // case 'M': max = mspectou32(optarg); break; | |||
| 83 | // case 'm': min = mspectou32(optarg); break; | |||
| 84 | case 'd': | |||
| 85 | initerrors(NULL((void*)0), -1, 1); /* showstatus */ | |||
| 86 | debug = 1; | |||
| 87 | break; | |||
| 88 | case 's': output = OUT_STD; break; | |||
| 89 | case 'c': output = OUT_CIDR; break; | |||
| 90 | case 'i': output = OUT_CISCO; break; | |||
| 91 | case 'r': output = OUT_RANGE; break; | |||
| 92 | case 'x': output = OUT_HEX; break; | |||
| 93 | case 'o': output = OUT_OCTAL; break; | |||
| 94 | case 'b': output = OUT_BINARY; break; | |||
| 95 | default: lose = 1; break; | |||
| 96 | } | |||
| 97 | if(v) { | |||
| 98 | if(v == 1) fprintf(stderrstderr, "%s\n", version); | |||
| 99 | else fprintf(stderrstderr, "%s, %s\n", version, vversion); | |||
| 100 | if(!h) exit(0); | |||
| 101 | } | |||
| 102 | if(h) { | |||
| 103 | fprintf(stderrstderr, | |||
| 104 | "This is netmask, an address netmask generation utility\n" | |||
| 105 | "Usage: %s spec [spec ...]\n" | |||
| 106 | " -h, --help\t\t\tPrint a summary of the options\n" | |||
| 107 | " -v, --version\t\t\tPrint the version number\n" | |||
| 108 | " -d, --debug\t\t\tPrint status/progress information\n" | |||
| 109 | " -s, --standard\t\tOutput address/netmask pairs\n" | |||
| 110 | " -c, --cidr\t\t\tOutput CIDR format address lists\n" | |||
| 111 | " -i, --cisco\t\t\tOutput Cisco style address lists\n" | |||
| 112 | " -r, --range\t\t\tOutput ip address ranges\n" | |||
| 113 | " -x, --hex\t\t\tOutput address/netmask pairs in hex\n" | |||
| 114 | " -o, --octal\t\t\tOutput address/netmask pairs in octal\n" | |||
| 115 | " -b, --binary\t\t\tOutput address/netmask pairs in binary\n" | |||
| 116 | " -n, --nodns\t\t\tDisable DNS lookups for addresses\n" | |||
| 117 | // " -M, --max mask\t\tLimit maximum mask size\n" | |||
| 118 | // " -m, --min mask\t\tLimit minimum mask size (drop small ranges)\n" | |||
| 119 | "Definitions:\n" | |||
| 120 | " a spec can be any of:\n" | |||
| 121 | " address\n" | |||
| 122 | " address:address\n" | |||
| 123 | " address:+address\n" | |||
| 124 | " address/mask\n" | |||
| 125 | " an address can be any of:\n" | |||
| 126 | " N\t\tdecimal number\n" | |||
| 127 | " 0N\t\toctal number\n" | |||
| 128 | " 0xN\t\thex number\n" | |||
| 129 | " N.N.N.N\tdotted quad\n" | |||
| 130 | " hostname\tdns domain name\n" | |||
| 131 | " a mask is the number of bits set to one from the left\n", progname); | |||
| 132 | exit(0); | |||
| 133 | } | |||
| 134 | if(lose || optind == argc) { | |||
| 135 | fprintf(stderrstderr, usage, progname); | |||
| 136 | exit(1); | |||
| 137 | } | |||
| 138 | while(optind < argc) spectoaml(argv[optind++], dns); | |||
| 139 | display(output); | |||
| 140 | return(0); | |||
| 141 | } | |||
| 142 | ||||
| 143 | /************************************** | |||
| 144 | * PART I - Read input * | |||
| 145 | **************************************/ | |||
| 146 | ||||
| 147 | static u_int32_t aspectou32(char *, int); | |||
| 148 | static int rangetoaml(u_int32_t, u_int32_t); | |||
| 149 | static int strtou32(u_int32_t *, char *); | |||
| 150 | #ifndef HAVE_STRTOUL1 | |||
| 151 | static u_int32_t strtoul(const char *nptr, char **endptr, int base); | |||
| 152 | #endif | |||
| 153 | ||||
| 154 | /* spectoaml adds a spec to the aml. | |||
| 155 | * deals with: | |||
| 156 | * "address" | |||
| 157 | * "address:address" | |||
| 158 | * "address:+address" | |||
| 159 | * "address/mask" */ | |||
| 160 | int spectoaml(char *addrspec, int dns) { | |||
| 161 | char *sep; | |||
| 162 | u_int32_t addr; | |||
| 163 | ||||
| 164 | if((sep = strchr(addrspec, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (addrspec) && (':') == '\0' ? (char *) __rawmemchr ( addrspec, ':') : __builtin_strchr (addrspec, ':')))) != NULL((void*)0)) { /* range */ | |||
| 165 | u_int32_t addr2; | |||
| 166 | ||||
| 167 | *sep++ = '\0'; | |||
| 168 | addr = aspectou32(addrspec, dns); | |||
| 169 | if(*sep == '+') { | |||
| 170 | sep++; | |||
| 171 | addr2 = addr; | |||
| 172 | } else addr2 = 0; | |||
| 173 | addr2 += aspectou32(sep, dns); | |||
| 174 | rangetoaml(addr, addr2); | |||
| 175 | } else if((sep = strchr(addrspec, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p (addrspec) && ('/') == '\0' ? (char *) __rawmemchr ( addrspec, '/') : __builtin_strchr (addrspec, '/')))) != NULL((void*)0)) { /* mask */ | |||
| 176 | u_int32_t mask; | |||
| 177 | ||||
| 178 | *sep++ = '\0'; | |||
| 179 | addr = aspectou32(addrspec, dns); | |||
| 180 | mask = mspectou32(sep); | |||
| 181 | addtoaml(addr, mask); | |||
| 182 | } else { /* host */ | |||
| 183 | addr = aspectou32(addrspec, dns); | |||
| 184 | addtoaml(addr, ~0); | |||
| 185 | } | |||
| 186 | return(0); | |||
| 187 | } | |||
| 188 | /* aspectou32 should convert the address portion of a spec... | |||
| 189 | * "base10" | |||
| 190 | * "0base8" | |||
| 191 | * "0xbase16" | |||
| 192 | * "hostname" | |||
| 193 | * "address" */ | |||
| 194 | static u_int32_t aspectou32(char *astr, int dns) { | |||
| 195 | u_int32_t addr; | |||
| 196 | struct hostent *h; | |||
| 197 | struct in_addr s; | |||
| 198 | ||||
| 199 | if(strtou32(&addr, astr)); | |||
| 200 | else if(dns && ((h = gethostbyname(astr)) != NULL((void*)0))) | |||
| 201 | addr = ntohl(*((u_int32_t *)h->h_addr_list[0]))(__extension__ ({ unsigned int __v, __x = (*((u_int32_t *)h-> h_addr_list[0])); if (__builtin_constant_p (__x)) __v = ((((__x ) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff ) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" ( __x)); __v; })); | |||
| 202 | else if(inet_aton(astr, &s)) | |||
| 203 | addr = ntohl(s.s_addr)(__extension__ ({ unsigned int __v, __x = (s.s_addr); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x ) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ( "bswap %0" : "=r" (__v) : "0" (__x)); __v; })); | |||
| 204 | else panic("unable to parse \"%s\"", astr); | |||
| 205 | return(addr); | |||
| 206 | } | |||
| 207 | /* mspectou32 should convert the mask portion of a spec... | |||
| 208 | * "base10" | |||
| 209 | * "0base8" | |||
| 210 | * "0xbase16" | |||
| 211 | * "address" */ | |||
| 212 | static u_int32_t mspectou32(char *mstr) { | |||
| 213 | u_int32_t mask = 0, num; | |||
| 214 | struct in_addr s; | |||
| 215 | ||||
| 216 | if(strtou32(&num, mstr)) mask = num ? ~0 << (32 - num) : num; | |||
| 217 | else if(inet_aton(mstr, &s)) { | |||
| 218 | mask = ntohl(s.s_addr)(__extension__ ({ unsigned int __v, __x = (s.s_addr); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x ) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ( "bswap %0" : "=r" (__v) : "0" (__x)); __v; })); | |||
| 219 | for(num = ~mask; num & 1; num >>= 1); | |||
| 220 | if(num) { | |||
| 221 | for(num = mask; num & 1; num >>= 1); | |||
| 222 | if(num) panic("invalid mask 0x%08x from \"%s\"", mask, mstr); | |||
| 223 | mask = ~mask; | |||
| 224 | } | |||
| 225 | } else panic("unable to parse \"%s\"", mstr); | |||
| 226 | return(mask); | |||
| 227 | } | |||
| 228 | /* strtou32 shuld take an int pointer and a string looking like... | |||
| 229 | * "base10" | |||
| 230 | * "0base8" | |||
| 231 | * "0xbase16" | |||
| 232 | * and write the value as an unsigned 32 bit int | |||
| 233 | * returning true on success and false on failure */ | |||
| 234 | static int strtou32(u_int32_t *num, char *istr) { | |||
| 235 | u_int32_t value, base; | |||
| 236 | char *str, *endp; | |||
| 237 | ||||
| 238 | if(istr == NULL((void*)0) || *istr == '\0') return(0); | |||
| 239 | if(istr[0] == '0' && istr[1]) { | |||
| 240 | if(istr[1] == 'x' && istr[2]) { | |||
| 241 | base = 16; | |||
| 242 | str = istr + 2; | |||
| 243 | } else { | |||
| 244 | base = 8; | |||
| 245 | str = istr + 1; | |||
| 246 | } | |||
| 247 | } else { | |||
| 248 | base = 10; | |||
| 249 | str = istr; | |||
| 250 | } | |||
| 251 | value = strtoul(str, &endp, base); | |||
| 252 | if(*endp != '\0') return(0); | |||
| 253 | *num = value; | |||
| 254 | return(1); | |||
| 255 | } | |||
| 256 | /* range to aml should take two addresses | |||
| 257 | * and add the shortest list of address/mask pairs between them */ | |||
| 258 | static int rangetoaml(u_int32_t low, u_int32_t high) { | |||
| 259 | u_int32_t i, j, lxh; | |||
| 260 | ||||
| 261 | if(low > high) { | |||
| 262 | i = low; | |||
| 263 | low = high; | |||
| 264 | high = i; | |||
| 265 | } | |||
| 266 | for(lxh = i = low ^ high; i & 1; i >>= 1); | |||
| 267 | if(i == 0 && (low | lxh) == high) addtoaml(low, ~(high - low)); | |||
| 268 | else { | |||
| 269 | for(i = lxh, j = 0; i >> 1; j++) i >>= 1; | |||
| 270 | i <<= j; | |||
| 271 | i = ~(i - 1) & high; | |||
| 272 | rangetoaml(low, i - 1); | |||
| 273 | rangetoaml(i, high); | |||
| 274 | } | |||
| 275 | return(0); | |||
| 276 | } | |||
| 277 | #ifndef HAVE_STRTOUL1 | |||
| 278 | #warning no ISO 9899 strtoul()? enabling sub-optimal workaround. | |||
| 279 | static u_int32_t strtoul(const char *nptr, char **endptr, int base) { | |||
| 280 | char *fmt; | |||
| 281 | u_int32_t val; | |||
| 282 | ||||
| 283 | switch(base) { | |||
| 284 | case 8: fmt = "%lo"; break; | |||
| 285 | case 10: fmt = "%lu"; break; | |||
| 286 | case 16: fmt = "%lx"; break; | |||
| 287 | } | |||
| 288 | if(sscanf(nptr, fmt, &val) > 0) *endptr = ""; | |||
| 289 | else *endptr = nptr; | |||
| 290 | return(val); | |||
| 291 | } | |||
| 292 | #endif | |||
| 293 | ||||
| 294 | /************************************** | |||
| 295 | * PART II - List management * | |||
| 296 | **************************************/ | |||
| 297 | ||||
| 298 | static int optimize(void); | |||
| 299 | ||||
| 300 | /* addtoaml takes an address and mask | |||
| 301 | * and adds it to the list | |||
| 302 | * note: it's a little bigger than it needs to be, | |||
| 303 | * but it's very modest about memory use | |||
| 304 | * and efficient enough considering it's use in optimize() */ | |||
| 305 | int addtoaml(u_int32_t addr, u_int32_t mask) { | |||
| 306 | int neta = addr & mask; | |||
| 307 | char first = 0; | |||
| 308 | struct addrmask *cur = aml, *lst = NULL((void*)0), | |||
| 309 | *src = NULL((void*)0), *dst = NULL((void*)0), *old = NULL((void*)0); | |||
| 310 | ||||
| 311 | if(aml == NULL((void*)0) || aml->mask > mask || | |||
| 312 | (aml->mask == mask && aml->neta > neta)) first = 1; | |||
| 313 | else { | |||
| 314 | for(cur = aml; cur && (cur->mask < mask || | |||
| 315 | (cur->mask == mask && cur->neta <= neta)); lst = cur, cur = cur->next) | |||
| 316 | if(cur->neta == (neta & cur->mask)) { | |||
| 317 | status("skip %08x/%08x (%08x/%08x exists)", | |||
| 318 | neta, mask, cur->neta, cur->mask); | |||
| 319 | return(0); | |||
| 320 | } | |||
| 321 | dst = lst; | |||
| 322 | } | |||
| 323 | while(cur) { | |||
| 324 | if(neta == (cur->neta & mask)) { | |||
| 325 | status("pull %08x/%08x (%08x/%08x added)", | |||
| 326 | cur->neta, cur->mask, neta, mask); | |||
| 327 | old = cur; | |||
| 328 | cur = cur->next; | |||
| 329 | if(old->prev) old->prev->next = old->next; | |||
| 330 | if(old->next) old->next->prev = old->prev; | |||
| 331 | if(aml == old) aml = cur; // suggested by Erik Gavert <erik@jsdata.se> | |||
| 332 | if(!old->prev && !old->next) { | |||
| 333 | aml = cur = NULL((void*)0); | |||
| 334 | first = 1; | |||
| 335 | } | |||
| 336 | if(!src) src = old; | |||
| 337 | else free(old); | |||
| 338 | } else cur = cur->next; | |||
| 339 | } | |||
| 340 | if(!src && (src = (struct addrmask *)malloc(sizeof(struct addrmask))) | |||
| 341 | == NULL((void*)0)) panic("malloc failure"); | |||
| 342 | src->neta = neta; | |||
| 343 | src->mask = mask; | |||
| 344 | if(first) { | |||
| 345 | status("add first {%08x/%08x}%08x/%08x", | |||
| 346 | neta, mask, aml?aml->neta:0, aml?aml->mask:0); | |||
| 347 | src->prev = NULL((void*)0); | |||
| 348 | src->next = aml; | |||
| 349 | if(aml) aml->prev = src; | |||
| 350 | aml = src; | |||
| 351 | } else if(dst) { | |||
| 352 | status("add middle %08x/%08x{%08x/%08x}%08x/%08x", | |||
| 353 | dst->neta, dst->mask, | |||
| 354 | neta, mask, | |||
| 355 | dst->next?dst->next->neta:0, dst->next?dst->next->mask:0); | |||
| 356 | src->prev = dst; | |||
| 357 | src->next = dst->next; | |||
| 358 | dst->next = src; | |||
| 359 | if(src->next) src->next->prev = src; | |||
| 360 | } else { | |||
| 361 | status("add last %08x/%08x{%08x/%08x}", | |||
| 362 | lst->neta, lst->mask, neta, mask); | |||
| 363 | src->prev = lst; | |||
| 364 | src->next = NULL((void*)0); | |||
| 365 | lst->next = src; | |||
| 366 | } | |||
| 367 | while(optimize()); | |||
| 368 | return(0); | |||
| 369 | } | |||
| 370 | ||||
| 371 | /* optimize - joins two AMs that can be expressed by a larger mask. */ | |||
| 372 | static int optimize(void) { | |||
| 373 | struct addrmask *cur; | |||
| 374 | ||||
| 375 | for(cur = aml; cur->next; cur = cur->next) | |||
| 376 | if(cur->mask == cur->next->mask && | |||
| 377 | cur->neta == (cur->next->neta & (cur->mask << 1))) { | |||
| 378 | addtoaml(cur->neta, cur->mask << 1); | |||
| 379 | return(1); | |||
| 380 | } | |||
| 381 | return(0); | |||
| 382 | } | |||
| 383 | ||||
| 384 | /************************************** | |||
| 385 | * PART III - Output formatting * | |||
| 386 | **************************************/ | |||
| 387 | ||||
| 388 | static int dispcidr(struct addrmask *); | |||
| 389 | static int dispstd(struct addrmask *); | |||
| 390 | static int dispcisco(struct addrmask *); | |||
| 391 | static int disprange(struct addrmask *); | |||
| 392 | static int disphex(struct addrmask *); | |||
| 393 | static int dispoctal(struct addrmask *); | |||
| 394 | static int dispbinary(struct addrmask *); | |||
| 395 | ||||
| 396 | /* display - shows the aml in a format specified by style | |||
| 397 | * it destroys the list as it sorts */ | |||
| 398 | int display(output_t style) { | |||
| 399 | struct addrmask *am, *list; | |||
| 400 | int (*disp)(struct addrmask *) = NULL((void*)0); | |||
| 401 | ||||
| 402 | switch(style) { | |||
| ||||
| 403 | case OUT_STD: disp = &dispstd; break; | |||
| 404 | case OUT_CIDR: disp = &dispcidr; break; | |||
| 405 | case OUT_CISCO: disp = &dispcisco; break; | |||
| 406 | case OUT_RANGE: disp = &disprange; break; | |||
| 407 | case OUT_HEX: disp = &disphex; break; | |||
| 408 | case OUT_OCTAL: disp = &dispoctal; break; | |||
| 409 | case OUT_BINARY: disp = &dispbinary; break; | |||
| 410 | default: panic("memfrob() apparently called on code segment"); | |||
| 411 | } | |||
| 412 | while(aml) { | |||
| 413 | am = NULL((void*)0); | |||
| 414 | for(list = aml; list; list = list->next) | |||
| ||||
| 415 | if(!am || am->neta > list->neta) am = list; | |||
| 416 | if(am->next) am->next->prev = am->prev; | |||
| 417 | if(am->prev) am->prev->next = am->next; | |||
| 418 | else aml = am->next; | |||
| 419 | disp(am); | |||
| 420 | free(am); | |||
| 421 | } | |||
| 422 | return(0); | |||
| 423 | } | |||
| 424 | ||||
| 425 | static int dispcidr(struct addrmask *am) { | |||
| 426 | u_int32_t mask; | |||
| 427 | int ctr = 0; | |||
| 428 | ||||
| 429 | for(mask = am->mask; mask; mask <<= 1) ctr++; | |||
| 430 | printf("%15s/%d\n", inet_ntoa((struct in_addr){htonl(am->neta)(__extension__ ({ unsigned int __v, __x = (am->neta); if ( __builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00 ) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }))}), ctr); | |||
| 431 | return(0); | |||
| 432 | } | |||
| 433 | static int dispstd(struct addrmask *am) { | |||
| 434 | char buf[32]; | |||
| 435 | ||||
| 436 | sprintf(buf, "%15s/", inet_ntoa((struct in_addr){htonl(am->neta)(__extension__ ({ unsigned int __v, __x = (am->neta); if ( __builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00 ) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }))})); | |||
| 437 | sprintf(buf + 16, "%-15s", inet_ntoa((struct in_addr){htonl(am->mask)(__extension__ ({ unsigned int __v, __x = (am->mask); if ( __builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00 ) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }))})); | |||
| 438 | puts(buf); | |||
| 439 | return(0); | |||
| 440 | } | |||
| 441 | static int dispcisco(struct addrmask *am) { | |||
| 442 | char buf[32]; | |||
| 443 | ||||
| 444 | sprintf(buf, "%15s ", inet_ntoa((struct in_addr){htonl(am->neta)(__extension__ ({ unsigned int __v, __x = (am->neta); if ( __builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00 ) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }))})); | |||
| 445 | sprintf(buf + 16, "%-15s", inet_ntoa((struct in_addr){htonl(~am->mask)(__extension__ ({ unsigned int __v, __x = (~am->mask); if ( __builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00 ) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }))})); | |||
| 446 | puts(buf); | |||
| 447 | return(0); | |||
| 448 | } | |||
| 449 | static int disprange(struct addrmask *am) { | |||
| 450 | char buf[80]; | |||
| 451 | u_int32_t range = ~am->mask + 1; | |||
| 452 | ||||
| 453 | sprintf(buf, "%15s-", inet_ntoa((struct in_addr){htonl(am->neta)(__extension__ ({ unsigned int __v, __x = (am->neta); if ( __builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00 ) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }))})); | |||
| 454 | sprintf(buf + 16, "%-15s (%u)", | |||
| 455 | inet_ntoa((struct in_addr){htonl(am->neta + range - 1)(__extension__ ({ unsigned int __v, __x = (am->neta + range - 1); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000 ) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x ) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v ; }))}), range); | |||
| 456 | puts(buf); | |||
| 457 | return(0); | |||
| 458 | } | |||
| 459 | static int disphex(struct addrmask *am) { | |||
| 460 | printf("0x%08x/0x%08x\n", am->neta, am->mask); | |||
| 461 | return(0); | |||
| 462 | } | |||
| 463 | static int dispoctal(struct addrmask *am) { | |||
| 464 | printf("0%10o/0%10o\n", am->neta, am->mask); | |||
| 465 | return(0); | |||
| 466 | } | |||
| 467 | static int dispbinary(struct addrmask *am) { | |||
| 468 | char abuf[36], mbuf[36]; | |||
| 469 | int i, j; | |||
| 470 | ||||
| 471 | for(i = 0; i < 32; i++) { | |||
| 472 | j = 34 - (int)(i * 9 / 8); /* array index skips every 9th element */ | |||
| 473 | abuf[j] = am->neta & 1 ? '1' : '0'; | |||
| 474 | mbuf[j] = am->mask & 1 ? '1' : '0'; | |||
| 475 | am->neta >>= 1; | |||
| 476 | am->mask >>= 1; | |||
| 477 | } | |||
| 478 | abuf[8] = abuf[17] = abuf[26] = mbuf[8] = mbuf[17] = mbuf[26] = ' '; | |||
| 479 | abuf[35] = mbuf[35] = '\0'; | |||
| 480 | printf("%s / %s\n", abuf, mbuf); | |||
| 481 | return(0); | |||
| 482 | } |