Annotation of embedaddon/mpd/src/ip.c, revision 1.1.1.1
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:
261: struct u_addr *u_addrcopy(const struct u_addr *src, struct u_addr *dst)
262: {
263: return memcpy(dst,src,sizeof(struct u_addr));
264: }
265:
266: struct u_addr *u_rangecopy(const struct u_range *src, struct u_range *dst)
267: {
268: return memcpy(dst,src,sizeof(struct u_range));
269: }
270:
271: struct u_addr *u_addrclear(struct u_addr *addr)
272: {
273: memset(addr,0,sizeof(struct u_addr));
274: return addr;
275: }
276:
277: struct u_range *u_rangeclear(struct u_range *range)
278: {
279: memset(range,0,sizeof(struct u_range));
280: return range;
281: }
282:
283: struct u_addr *in_addrtou_addr(const struct in_addr *src, struct u_addr *dst)
284: {
285: u_addrclear(dst);
286: dst->family=AF_INET;
287: dst->u.ip4=*src;
288: return dst;
289: }
290:
291: struct u_addr *in6_addrtou_addr(const struct in6_addr *src, struct u_addr *dst)
292: {
293: u_addrclear(dst);
294: dst->family=AF_INET6;
295: dst->u.ip6=*src;
296: return dst;
297: }
298:
299: struct in_addr *u_addrtoin_addr(const struct u_addr *src, struct in_addr *dst)
300: {
301: *dst=src->u.ip4;
302: return dst;
303: }
304:
305: struct in6_addr *u_addrtoin6_addr(const struct u_addr *src, struct in6_addr *dst)
306: {
307: *dst=src->u.ip6;
308: return dst;
309: }
310:
311: struct u_range *in_addrtou_range(const struct in_addr *src, u_char width, struct u_range *dst)
312: {
313: u_rangeclear(dst);
314: in_addrtou_addr(src, &dst->addr);
315: dst->width = width;
316: return dst;
317: }
318:
319: struct u_range *in6_addrtou_range(const struct in6_addr *src, u_char width, struct u_range *dst)
320: {
321: u_rangeclear(dst);
322: in6_addrtou_addr(src, &dst->addr);
323: dst->width = width;
324: return dst;
325: }
326:
327: int u_addrempty(struct u_addr *addr)
328: {
329: int i;
330: switch (addr->family) {
331: case AF_INET:
332: return (addr->u.ip4.s_addr==0);
333: break;
334: case AF_INET6:
335: for (i=0;i<16;i++) {
336: if (addr->u.ip6.s6_addr[i]!=0)
337: return 0;
338: }
339: return 1;
340: break;
341: }
342: return 1;
343: }
344:
345: int u_rangeempty(struct u_range *range)
346: {
347: return u_addrempty(&range->addr);
348: }
349:
350: int u_rangehost(struct u_range *range)
351: {
352: switch (range->addr.family) {
353: case AF_INET:
354: return (range->width==32);
355: break;
356: case AF_INET6:
357: return (range->width==128);
358: break;
359: }
360: return 0;
361: }
362:
363: static struct in6_addr
364: bits2mask6(int bits)
365: {
366: struct in6_addr result;
367: u_int32_t bit = 0x80;
368: u_char *c = result.s6_addr;
369:
370: memset(&result, '\0', sizeof(result));
371:
372: while (bits) {
373: if (bit == 0) {
374: bit = 0x80;
375: c++;
376: }
377: *c |= bit;
378: bit >>= 1;
379: bits--;
380: }
381:
382: return result;
383: }
384:
385: struct sockaddr_storage *u_rangetosockaddrs(struct u_range *range, struct sockaddr_storage *dst, struct sockaddr_storage *msk)
386: {
387: memset(dst,0,sizeof(struct sockaddr_storage));
388: memset(msk,0,sizeof(struct sockaddr_storage));
389: dst->ss_family = msk->ss_family = range->addr.family;
390: switch (range->addr.family) {
391: case AF_INET:
392: ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
393: ((struct sockaddr_in*)dst)->sin_addr=range->addr.u.ip4;
394: ((struct sockaddr_in*)msk)->sin_len=sizeof(struct sockaddr_in);
395: ((struct sockaddr_in*)msk)->sin_addr.s_addr=htonl(0xFFFFFFFFLL<<(32 - range->width));
396: break;
397: case AF_INET6:
398: ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
399: ((struct sockaddr_in6*)dst)->sin6_addr=range->addr.u.ip6;
400: ((struct sockaddr_in6*)msk)->sin6_len=sizeof(struct sockaddr_in6);
401: ((struct sockaddr_in6*)msk)->sin6_addr=bits2mask6(range->width);
402: break;
403: default:
404: dst->ss_len=sizeof(struct sockaddr_storage);
405: break;
406: }
407: return dst;
408: }
409:
410: struct sockaddr_storage *u_addrtosockaddr(struct u_addr *addr, in_port_t port, struct sockaddr_storage *dst)
411: {
412: memset(dst,0,sizeof(struct sockaddr_storage));
413: dst->ss_family=addr->family;
414: switch (addr->family) {
415: case AF_INET:
416: ((struct sockaddr_in*)dst)->sin_len=sizeof(struct sockaddr_in);
417: ((struct sockaddr_in*)dst)->sin_addr=addr->u.ip4;
418: ((struct sockaddr_in*)dst)->sin_port=htons(port);
419: break;
420: case AF_INET6:
421: ((struct sockaddr_in6*)dst)->sin6_len=sizeof(struct sockaddr_in6);
422: ((struct sockaddr_in6*)dst)->sin6_addr=addr->u.ip6;
423: ((struct sockaddr_in6*)dst)->sin6_port=htons(port);
424: break;
425: default:
426: dst->ss_len=sizeof(struct sockaddr_storage);
427: break;
428: }
429: return dst;
430: }
431:
432: void sockaddrtou_addr(struct sockaddr_storage *src, struct u_addr *addr, in_port_t *port)
433: {
434: addr->family=src->ss_family;
435: switch (addr->family) {
436: case AF_INET:
437: addr->u.ip4=((struct sockaddr_in*)src)->sin_addr;
438: *port=ntohs(((struct sockaddr_in*)src)->sin_port);
439: break;
440: case AF_INET6:
441: addr->u.ip6=((struct sockaddr_in6*)src)->sin6_addr;
442: *port=ntohs(((struct sockaddr_in6*)src)->sin6_port);
443: break;
444: default:
445: memset(addr,0,sizeof(struct u_addr));
446: *port=0;
447: break;
448: }
449: }
450:
451: int u_addrcompare(const struct u_addr *addr1, const struct u_addr *addr2)
452: {
453: int i;
454:
455: if (addr1->family<addr2->family)
456: return(-1);
457: else if (addr1->family>addr2->family)
458: return(1);
459:
460: switch (addr1->family) {
461: case AF_INET:
462: if (addr1->u.ip4.s_addr < addr2->u.ip4.s_addr)
463: return (-1);
464: else if (addr1->u.ip4.s_addr == addr2->u.ip4.s_addr)
465: return (0);
466: else
467: return (1);
468: break;
469: case AF_INET6:
470: for (i=0; i<16; i++) {
471: if (addr1->u.ip6.s6_addr[i] < addr2->u.ip6.s6_addr[i])
472: return (-1);
473: else if (addr1->u.ip6.s6_addr[i] > addr2->u.ip6.s6_addr[i])
474: return (1);
475: }
476: return 0;
477: break;
478: }
479: return 0;
480: }
481:
482: int u_rangecompare(const struct u_range *range1, const struct u_range *range2)
483: {
484: if (range1->width<range2->width)
485: return(-1);
486: else if (range1->width>range2->width)
487: return(1);
488:
489: return u_addrcompare(&range1->addr,&range2->addr);
490: }
491:
492: uint32_t
493: u_addrtoid(const struct u_addr *addr)
494: {
495: uint32_t id;
496:
497: if (addr->family==AF_INET) {
498: id = ntohl(addr->u.ip4.s_addr);
499: } else if (addr->family==AF_INET6) {
500: uint32_t *a32 = (uint32_t *)(&addr->u.ip6.s6_addr[0]);
501: id = a32[0] + a32[1] + a32[2] + a32[3];
502: } else {
503: id = 0;
504: }
505:
506: return (id);
507: }
508:
509: u_char
510: in_addrtowidth(struct in_addr *mask)
511: {
512: u_char width = 0;
513: uint32_t m = ntohl(mask->s_addr);
514:
515: while ((m & 0x80000000) != 0) {
516: m <<= 1;
517: width++;
518: }
519: return (width);
520: }
521:
522: struct in_addr *
523: widthtoin_addr(u_char width, struct in_addr *mask)
524: {
525: mask->s_addr = htonl(0xFFFFFFFF << (32 - width));
526: return (mask);
527: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>