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