Annotation of embedaddon/mpd/src/ip.c, revision 1.1.1.2
1.1 misho 1:
2: /*
3: * ip.c
4: *
5: * Written by Alexander Motin <mav@FreeBSD.org>
6: */
7:
8: #include "ppp.h"
9: #include "ip.h"
10: #include "util.h"
11:
12: /*
13: * IpShowRoutes()
14: *
15: * Show routing tables
16: */
17:
18: int
19: IpShowRoutes(Context ctx, int ac, char *av[], void *arg)
20: {
21: FILE *fp;
22: char buf[256];
23: char *c;
24:
25: if ((fp = popen(PATH_NETSTAT " -nr -f inet", "r")) == NULL)
26: {
27: Perror("popen");
28: return(CMD_ERR_OTHER);
29: }
30: while (fgets(buf,sizeof(buf)-1,fp)) {
31: if ((c=strrchr(buf,'\n')))
32: *c='\r';
33: Printf("%s\n",buf);
34: }
35: pclose(fp);
36: return(0);
37: }
38:
39: /*
40: * IpAddrInRange()
41: *
42: * Is the IP address within the range?
43: */
44:
45: int
46: IpAddrInRange(struct u_range *range, struct u_addr *addr)
47: {
48: u_int32_t mask;
49: u_int8_t bmask;
50: int i;
51:
52: if (u_rangeempty(range))
53: return(1); // For compatibility we think that empty range includes any ip.
54:
55: if (range->addr.family!=addr->family)
56: return(0);
57:
58: switch (range->addr.family) {
59: case AF_INET:
60: mask = range->width ? htonl(~0 << (32 - range->width)) : 0;
61: return((addr->u.ip4.s_addr & mask) == (range->addr.u.ip4.s_addr & mask));
62: break;
63: case AF_INET6:
64: for (i=0; i<((range->width+7)/8); i++) {
65: if ((i*8+7)<range->width) {
66: if (addr->u.ip6.s6_addr[i]!=range->addr.u.ip6.s6_addr[i])
67: return 0;
68: } else {
69: bmask=(range->width==i*8)? 0 : (~0 << (8 - range->width));
70: if ((addr->u.ip6.s6_addr[i] & bmask) != (range->addr.u.ip6.s6_addr[i] & bmask))
71: return 0;
72: }
73: }
74: return 1;
75: break;
76: }
77: return 0;
78: }
79:
80: /*
81: * ParseAddr()
82: *
83: * Parse an IP address & mask of the form X.Y.Z.W/M.
84: * If no slash, then M is assumed to be 32.
85: * Returns TRUE if successful
86: */
87:
88: int
89: ParseAddr(const char *s, struct u_addr *addr, u_char allow)
90: {
91: if (strchr(s, '/'))
92: return (FALSE);
93:
94: /* Get IP address part; if that fails, try looking up hostname */
95:
96: if ((allow&ALLOW_IPV4) && inet_pton(AF_INET, s, &addr->u.ip4))
97: {
98: addr->family=AF_INET;
99: }
100: else if ((allow&ALLOW_IPV6) && inet_pton(AF_INET6, s, &addr->u.ip6))
101: {
102: addr->family=AF_INET6;
103: }
104: else if ((allow&ALLOW_IPV4) && !GetAnyIpAddress(addr, s))
105: {
106: addr->family=AF_INET;
107: }
108: else if (allow&ALLOW_IPV4)
109: {
110: struct hostent *hptr;
111: int k;
112:
113: if ((hptr = gethostbyname(s)) == NULL) {
114: return (FALSE);
115: }
116: for (k = 0; hptr->h_addr_list[k]; k++);
117: if (k == 0)
118: k = 1;
119: memcpy(&addr->u.ip4, hptr->h_addr_list[random() % k], sizeof(addr->u.ip4));
120: addr->family=AF_INET;
121: }
122: else
123: {
124: return (FALSE);
125: }
126:
127: return(TRUE);
128: }
129:
130: /*
131: * ParseRange()
132: *
133: * Parse an IP address & mask of the form X.Y.Z.W/M.
134: * If no slash, then M is assumed to be 32.
135: * Returns TRUE if successful
136: */
137:
138: int
139: ParseRange(const char *s, struct u_range *range, u_char allow)
140: {
141: int n_bits;
142: char *widp, buf[64];
143:
144: strlcpy(buf, s, sizeof(buf));
145: if ((widp = strchr(buf, '/')) != NULL)
146: *widp++ = '\0';
147: else
148: widp = buf + strlen(buf);
149:
150: /* Get IP address part; if that fails, try looking up hostname */
151:
152: if (!ParseAddr(buf, &range->addr, allow))
153: return(FALSE);
154:
155: /* Get mask width */
156:
157: if (*widp)
158: {
159: if ((n_bits = atoi(widp)) < 0 || (range->addr.family==AF_INET && n_bits > 32) || (range->addr.family==AF_INET6 && n_bits > 128))
160: {
161: return(FALSE);
162: }
163: }
164: else if (range->addr.family==AF_INET) {
165: n_bits = 32;
166: } else {
167: n_bits = 128;
168: }
169: range->width = n_bits;
170:
171: return(TRUE);
172: }
173:
174: /*
175: * ParseAddrPort()
176: *
177: * Parse an IP address & port of the form X.Y.Z.W P.
178: * Returns pointer to sockaddr_in. Not thread safe!
179: */
180:
181: struct sockaddr_storage *
182: ParseAddrPort(int ac, char *av[], u_char allow)
183: {
184: static struct sockaddr_storage ss;
185: struct u_addr addr;
186: int port = 0;
187:
188: if (ac < 1 || ac > 2)
189: return (NULL);
190:
191: if (!ParseAddr(av[0], &addr, allow))
192: return(NULL);
193:
194: if (ac > 1) {
195: if ((port = atoi(av[1])) < 1 || port > 65535) {
196: Log(LG_ERR, ("Bad port \"%s\"", av[1]));
197: return (NULL);
198: }
199: }
200:
201: memset(&ss, 0, sizeof(ss));
202: ss.ss_family = addr.family;
203: switch (addr.family) {
204: case AF_INET:
205: ss.ss_len = sizeof(struct sockaddr_in);
206: ((struct sockaddr_in*)&ss)->sin_addr = addr.u.ip4;
207: ((struct sockaddr_in*)&ss)->sin_port = htons(port);
208: break;
209: case AF_INET6:
210: ss.ss_len = sizeof(struct sockaddr_in6);
211: ((struct sockaddr_in6*)&ss)->sin6_addr = addr.u.ip6;
212: ((struct sockaddr_in6*)&ss)->sin6_port = htons(port);
213: break;
214: default:
215: ss.ss_len = sizeof(struct sockaddr_storage);
216: }
217:
218: return (&ss);
219: }
220:
221: sa_family_t u_addrfamily(struct u_addr *addr)
222: {
223: return addr->family;
224: }
225:
226: sa_family_t u_rangefamily(struct u_range *range)
227: {
228: return range->addr.family;
229: }
230:
231: char *u_addrtoa(struct u_addr *addr, char *dst, size_t size)
232: {
233: dst[0]=0;
234:
235: if (addr->family==AF_INET) {
236: inet_ntop(addr->family, &addr->u.ip4, dst, size);
237: }
238: else if (addr->family==AF_INET6)
239: {
240: inet_ntop(addr->family, &addr->u.ip6, dst, size);
241: }
242: else if (addr->family==AF_UNSPEC)
243: {
244: snprintf(dst,size,"UNSPEC");
245: }
246:
247: return dst;
248: }
249:
250: char *u_rangetoa(struct u_range *range, char *dst, size_t size)
251: {
252: if (!u_addrtoa(&range->addr, dst, size))
253: return NULL;
254:
255: if (range->addr.family!=AF_UNSPEC)
256: snprintf(dst+strlen(dst), size-strlen(dst), "/%d", range->width);
257:
258: return dst;
259: }
260:
1.1.1.2 ! misho 261: void u_addrcopy(const struct u_addr *src, struct u_addr *dst)
1.1 misho 262: {
1.1.1.2 ! misho 263: memcpy(dst,src,sizeof(struct u_addr));
1.1 misho 264: }
265:
1.1.1.2 ! misho 266: void u_rangecopy(const struct u_range *src, struct u_range *dst)
1.1 misho 267: {
1.1.1.2 ! misho 268: memcpy(dst,src,sizeof(struct u_range));
1.1 misho 269: }
270:
1.1.1.2 ! misho 271: void u_addrclear(struct u_addr *addr)
1.1 misho 272: {
273: memset(addr,0,sizeof(struct u_addr));
274: }
275:
1.1.1.2 ! misho 276: void u_rangeclear(struct u_range *range)
1.1 misho 277: {
278: memset(range,0,sizeof(struct u_range));
279: }
280:
1.1.1.2 ! misho 281: void in_addrtou_addr(const struct in_addr *src, struct u_addr *dst)
1.1 misho 282: {
283: u_addrclear(dst);
284: dst->family=AF_INET;
285: dst->u.ip4=*src;
286: }
287:
1.1.1.2 ! misho 288: void in6_addrtou_addr(const struct in6_addr *src, struct u_addr *dst)
1.1 misho 289: {
290: u_addrclear(dst);
291: dst->family=AF_INET6;
292: dst->u.ip6=*src;
293: }
294:
1.1.1.2 ! misho 295: void u_addrtoin_addr(const struct u_addr *src, struct in_addr *dst)
1.1 misho 296: {
297: *dst=src->u.ip4;
298: }
299:
1.1.1.2 ! misho 300: void u_addrtoin6_addr(const struct u_addr *src, struct in6_addr *dst)
1.1 misho 301: {
302: *dst=src->u.ip6;
303: }
304:
1.1.1.2 ! misho 305: void in_addrtou_range(const struct in_addr *src, u_char width, struct u_range *dst)
1.1 misho 306: {
307: u_rangeclear(dst);
308: in_addrtou_addr(src, &dst->addr);
309: dst->width = width;
310: }
311:
1.1.1.2 ! misho 312: void in6_addrtou_range(const struct in6_addr *src, u_char width, struct u_range *dst)
1.1 misho 313: {
314: u_rangeclear(dst);
315: in6_addrtou_addr(src, &dst->addr);
316: dst->width = width;
317: }
318:
319: int u_addrempty(struct u_addr *addr)
320: {
321: int i;
322: switch (addr->family) {
323: case AF_INET:
324: return (addr->u.ip4.s_addr==0);
325: break;
326: case AF_INET6:
327: for (i=0;i<16;i++) {
328: if (addr->u.ip6.s6_addr[i]!=0)
329: return 0;
330: }
331: return 1;
332: break;
333: }
334: return 1;
335: }
336:
337: int u_rangeempty(struct u_range *range)
338: {
339: return u_addrempty(&range->addr);
340: }
341:
342: int u_rangehost(struct u_range *range)
343: {
344: switch (range->addr.family) {
345: case AF_INET:
346: return (range->width==32);
347: break;
348: case AF_INET6:
349: return (range->width==128);
350: break;
351: }
352: return 0;
353: }
354:
355: static struct in6_addr
356: bits2mask6(int bits)
357: {
358: struct in6_addr result;
359: u_int32_t bit = 0x80;
360: u_char *c = result.s6_addr;
361:
362: memset(&result, '\0', sizeof(result));
363:
364: while (bits) {
365: if (bit == 0) {
366: bit = 0x80;
367: c++;
368: }
369: *c |= bit;
370: bit >>= 1;
371: bits--;
372: }
373:
374: return result;
375: }
376:
1.1.1.2 ! misho 377: void u_rangetosockaddrs(struct u_range *range, struct sockaddr_storage *dst, struct sockaddr_storage *msk)
1.1 misho 378: {
379: memset(dst,0,sizeof(struct sockaddr_storage));
380: memset(msk,0,sizeof(struct sockaddr_storage));
381: dst->ss_family = msk->ss_family = range->addr.family;
382: switch (range->addr.family) {
383: case AF_INET:
384: ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
385: ((struct sockaddr_in*)dst)->sin_addr=range->addr.u.ip4;
386: ((struct sockaddr_in*)msk)->sin_len=sizeof(struct sockaddr_in);
387: ((struct sockaddr_in*)msk)->sin_addr.s_addr=htonl(0xFFFFFFFFLL<<(32 - range->width));
388: break;
389: case AF_INET6:
390: ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
391: ((struct sockaddr_in6*)dst)->sin6_addr=range->addr.u.ip6;
392: ((struct sockaddr_in6*)msk)->sin6_len=sizeof(struct sockaddr_in6);
393: ((struct sockaddr_in6*)msk)->sin6_addr=bits2mask6(range->width);
394: break;
395: default:
396: dst->ss_len=sizeof(struct sockaddr_storage);
397: break;
398: }
399: }
400:
1.1.1.2 ! misho 401: void u_addrtosockaddr(struct u_addr *addr, in_port_t port, struct sockaddr_storage *dst)
1.1 misho 402: {
403: memset(dst,0,sizeof(struct sockaddr_storage));
404: dst->ss_family=addr->family;
405: switch (addr->family) {
406: case AF_INET:
407: ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
408: ((struct sockaddr_in*)dst)->sin_addr=addr->u.ip4;
409: ((struct sockaddr_in*)dst)->sin_port=htons(port);
410: break;
411: case AF_INET6:
412: ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
413: ((struct sockaddr_in6*)dst)->sin6_addr=addr->u.ip6;
414: ((struct sockaddr_in6*)dst)->sin6_port=htons(port);
415: break;
416: default:
417: dst->ss_len=sizeof(struct sockaddr_storage);
418: break;
419: }
420: }
421:
422: void sockaddrtou_addr(struct sockaddr_storage *src, struct u_addr *addr, in_port_t *port)
423: {
424: addr->family=src->ss_family;
425: switch (addr->family) {
426: case AF_INET:
427: addr->u.ip4=((struct sockaddr_in*)src)->sin_addr;
428: *port=ntohs(((struct sockaddr_in*)src)->sin_port);
429: break;
430: case AF_INET6:
431: addr->u.ip6=((struct sockaddr_in6*)src)->sin6_addr;
432: *port=ntohs(((struct sockaddr_in6*)src)->sin6_port);
433: break;
434: default:
435: memset(addr,0,sizeof(struct u_addr));
436: *port=0;
437: break;
438: }
439: }
440:
441: int u_addrcompare(const struct u_addr *addr1, const struct u_addr *addr2)
442: {
443: int i;
444:
445: if (addr1->family<addr2->family)
446: return(-1);
447: else if (addr1->family>addr2->family)
448: return(1);
449:
450: switch (addr1->family) {
451: case AF_INET:
452: if (addr1->u.ip4.s_addr < addr2->u.ip4.s_addr)
453: return (-1);
454: else if (addr1->u.ip4.s_addr == addr2->u.ip4.s_addr)
455: return (0);
456: else
457: return (1);
458: break;
459: case AF_INET6:
460: for (i=0; i<16; i++) {
461: if (addr1->u.ip6.s6_addr[i] < addr2->u.ip6.s6_addr[i])
462: return (-1);
463: else if (addr1->u.ip6.s6_addr[i] > addr2->u.ip6.s6_addr[i])
464: return (1);
465: }
466: return 0;
467: break;
468: }
469: return 0;
470: }
471:
472: int u_rangecompare(const struct u_range *range1, const struct u_range *range2)
473: {
474: if (range1->width<range2->width)
475: return(-1);
476: else if (range1->width>range2->width)
477: return(1);
478:
479: return u_addrcompare(&range1->addr,&range2->addr);
480: }
481:
482: uint32_t
483: u_addrtoid(const struct u_addr *addr)
484: {
485: uint32_t id;
486:
487: if (addr->family==AF_INET) {
488: id = ntohl(addr->u.ip4.s_addr);
489: } else if (addr->family==AF_INET6) {
490: uint32_t *a32 = (uint32_t *)(&addr->u.ip6.s6_addr[0]);
491: id = a32[0] + a32[1] + a32[2] + a32[3];
492: } else {
493: id = 0;
494: }
495:
496: return (id);
497: }
498:
499: u_char
500: in_addrtowidth(struct in_addr *mask)
501: {
502: u_char width = 0;
503: uint32_t m = ntohl(mask->s_addr);
504:
505: while ((m & 0x80000000) != 0) {
506: m <<= 1;
507: width++;
508: }
509: return (width);
510: }
511:
512: struct in_addr *
513: widthtoin_addr(u_char width, struct in_addr *mask)
514: {
515: mask->s_addr = htonl(0xFFFFFFFF << (32 - width));
516: return (mask);
517: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>