File: | netmask.c |
Location: | line 362, column 7 |
Description: | Access to field 'neta' results in a dereference of a null pointer (loaded from variable 'lst') |
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 | } |