File: | netmask.c |
Location: | line 86, column 5 |
Description: | Value stored to 'debug' is never read |
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; |
Value stored to 'debug' is never read | |
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 | } |