Annotation of libelwix/src/net.c, revision 1.10.10.7
1.1 misho 1: /*************************************************************************
2: * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.10.10.7! misho 6: * $Id: net.c,v 1.10.10.6 2014/12/11 01:51:24 misho Exp $
1.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.9 misho 15: Copyright 2004 - 2014
1.1 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
1.6 misho 49: static char hexlist[] = "0123456789abcdef";
50:
51: /*
52: * e_link_ntoa() - String ethernet address from link address
53: *
54: * @sdl = link address
55: * return: =NULL error or !=NULL ethernet address, should be e_free()
56: */
57: char *
58: e_link_ntoa(const struct sockaddr_dl *sdl)
59: {
60: static char obuf[64];
61: char *out = obuf;
62: int i;
63: u_char *in = (u_char*) LLADDR(sdl);
64: u_char *inlim = in + sdl->sdl_alen;
65: int firsttime = 1;
66:
67: if (sdl->sdl_nlen) {
68: memcpy(obuf, sdl->sdl_data, sdl->sdl_nlen);
69: out += sdl->sdl_nlen;
70: if (sdl->sdl_alen)
71: *out++ = '!';
72: }
73:
74: while (in < inlim) {
75: if (firsttime)
76: firsttime ^= firsttime;
77: else
78: *out++ = ':';
1.8 misho 79:
1.6 misho 80: i = *in++;
81: if (i > 0xf) {
82: out[1] = hexlist[i & 0xf];
83: i >>= 4;
1.8 misho 84: } else {
85: out[1] = hexlist[i];
86: i = 0;
87: }
1.6 misho 88:
89: out[0] = hexlist[i];
90: out += 2;
91: }
92:
93: *out = 0;
94: return obuf;
95: }
96:
1.1 misho 97: /*
1.10.10.4 misho 98: * e_link_addr() - String ethernet address to link address
99: *
100: * @mac = ethernet address
101: * @sdl = link address
102: * return: -1 error or 0 ok
103: */
104: int
105: e_link_addr(const char *mac, struct sockaddr_dl * __restrict sdl)
106: {
107: if (!mac || !sdl)
108: return -1;
109: if (!sdl->sdl_len)
110: sdl->sdl_len = sizeof(struct sockaddr_dl);
111:
112: link_addr(mac, sdl);
113: return 0;
114: }
115:
116: /*
1.1 misho 117: * e_ether_ntoa() - Convert ethernet address to string
118: *
119: * @n = ethernet address structure, like struct ether_addr
120: * @a = string
121: * @len = string length
122: * return: NULL error or !=NULL string a
123: */
1.2 misho 124: char *
1.7 misho 125: e_ether_ntoa(const ether_addr_t * __restrict n, char * __restrict a, int len)
1.1 misho 126: {
127: if (!n || !a)
128: return NULL;
129:
130: memset(a, 0, len);
1.8 misho 131: if (snprintf(a, len, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1.10.10.7! misho 132: n->octet[0], n->octet[1],
! 133: n->octet[2], n->octet[3],
! 134: n->octet[4], n->octet[5]) < 17)
1.1 misho 135: return NULL;
136:
137: return a;
138: }
139:
140: /*
141: * e_ether_aton() - Convert string to ethernet address
142: *
143: * @a = string
144: * @e = ethernet address structure, like struct ether_addr
145: * return: NULL error or !=NULL ethernet address structure
146: */
1.7 misho 147: ether_addr_t *
148: e_ether_aton(const char *a, ether_addr_t * __restrict e)
1.1 misho 149: {
150: int i;
151:
152: if (!a || !e)
153: return NULL;
154:
1.8 misho 155: i = sscanf(a, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
1.10.10.7! misho 156: &e->octet[0],
! 157: &e->octet[1],
! 158: &e->octet[2],
! 159: &e->octet[3],
! 160: &e->octet[4],
! 161: &e->octet[5]);
1.1 misho 162: if (i != 6)
163: return NULL;
164:
165: return e;
166: }
167:
168: /*
169: * e_n2port() - Extract port from network structure
170: *
171: * @addr = Address
172: * return: 0 not supported family type or port number
173: */
1.2 misho 174: u_short
1.1 misho 175: e_n2port(sockaddr_t * __restrict addr)
176: {
177: u_short port = 0;
178:
179: if (!addr)
180: return port;
181:
182: switch (addr->sa.sa_family) {
183: case AF_INET:
184: return ntohs(addr->sin.sin_port);
185: case AF_INET6:
186: return ntohs(addr->sin6.sin6_port);
187: default:
188: break;
189: }
190:
191: return port;
192: }
193:
194: /*
195: * e_n2addr() - Extract address from network structure
196: *
197: * @addr = Address
198: * @val = Value for store string address
199: * return: NULL error or !=NULL string address from val
200: */
201: const char *
202: e_n2addr(sockaddr_t * __restrict addr, ait_val_t * __restrict val)
203: {
1.5 misho 204: char *s, str[INET6_ADDRSTRLEN] = { 0 };
1.1 misho 205: const char *ret = NULL;
206:
207: if (!addr || !val)
208: return ret;
209:
210: AIT_INIT_VAL(val);
211: switch (addr->sa.sa_family) {
212: case AF_INET:
213: if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
214: LOGERR;
215: return ret;
216: } else
217: ret = str;
218: break;
219: case AF_INET6:
220: if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
221: LOGERR;
222: return ret;
223: } else
224: ret = str;
225: break;
226: case AF_LOCAL:
227: ret = addr->sun.sun_path;
228: break;
1.5 misho 229: case AF_LINK:
1.6 misho 230: if (!(s = e_link_ntoa(&addr->sdl))) {
1.5 misho 231: LOGERR;
232: return ret;
233: } else
234: ret = s;
235: break;
1.1 misho 236: default:
237: elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
238: addr->sa.sa_family);
239: return ret;
240: }
241:
242: AIT_SET_STR(val, ret);
243: return (const char*) AIT_GET_STR(val);
244: }
245:
246: /*
247: * e_gethostbyname() - Get host and port and make network structure
248: *
249: * @psHost = Hostname
250: * @port = Port
251: * @addr = Network address structure
252: * return: NULL error or !=NULL network structure
253: */
254: sockaddr_t *
255: e_gethostbyname(const char *psHost, u_short port, sockaddr_t * __restrict addr)
256: {
257: struct hostent *host = NULL;
258:
259: if (!psHost || !addr)
260: return NULL;
261:
262: if (*psHost != '/') {
263: /* resolver */
1.10 misho 264: host = gethostbyname2(psHost, !strchr(psHost, ':') ? AF_INET : AF_INET6);
1.1 misho 265: if (!host) {
266: elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
267: return NULL;
268: } else {
269: memset(addr, 0, sizeof(sockaddr_t));
270: addr->sa.sa_family = host->h_addrtype;
271: }
272: } else {
273: memset(addr, 0, sizeof(sockaddr_t));
274: addr->sa.sa_family = AF_LOCAL;
275: }
276:
277:
278: switch (addr->sa.sa_family) {
279: case AF_INET:
280: addr->sin.sin_len = sizeof(struct sockaddr_in);
281: addr->sin.sin_family = AF_INET;
282: addr->sin.sin_port = htons(port);
283: memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
284: return addr;
285: case AF_INET6:
286: addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
287: addr->sin6.sin6_family = AF_INET6;
288: addr->sin6.sin6_port = htons(port);
289: memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
290: return addr;
291: case AF_LOCAL:
292: addr->sun.sun_len = sizeof(struct sockaddr_un);
293: addr->sun.sun_family = AF_LOCAL;
294: memset(addr->sun.sun_path, 0, sizeof addr->sun.sun_path);
295: snprintf(addr->sun.sun_path, sizeof addr->sun.sun_path, "%s-%hu", psHost, port);
296: return addr;
297: default:
298: elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
299: break;
300: }
301:
302: return NULL;
303: }
304:
305: /*
306: * e_addrcmp() - Compare network addresses
307: *
308: * @a = 1st address
309: * @b = 2nd address
310: * @p = compare and ports, if family is AF_INET or AF_INET6
311: * return: 0 is equal or !=0 is different
312: */
313: int
314: e_addrcmp(sockaddr_t * __restrict a, sockaddr_t * __restrict b, int p)
315: {
316: if (a && b && a->sa.sa_family == b->sa.sa_family)
317: switch (a->sa.sa_family) {
318: case AF_LOCAL:
319: return strcmp(a->sun.sun_path, b->sun.sun_path);
320: case AF_INET:
321: if (p && (a->sin.sin_port - b->sin.sin_port))
322: return (int) !!(a->sin.sin_port - b->sin.sin_port);
323: else
324: return memcmp(&a->sin.sin_addr, &b->sin.sin_addr,
325: sizeof a->sin.sin_addr);
326: case AF_INET6:
327: if (p && (a->sin6.sin6_port - b->sin6.sin6_port))
328: return (int) !!(a->sin6.sin6_port - b->sin6.sin6_port);
329: else
330: return memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr,
331: sizeof a->sin6.sin6_addr);
332: case AF_LINK:
333: return memcmp(&a->sdl.sdl_data, &b->sdl.sdl_data,
334: sizeof a->sdl.sdl_data);
335: }
336:
337: return (int) !!(a - b);
338: }
339:
340: /*
341: * e_usleep() - usleep() replacement for ELWIX
342: *
343: * @usec = microseconds for sleep
344: * return: -1 interrupted by signal or 0 ok
345: */
1.2 misho 346: int
1.1 misho 347: e_usleep(u_int usec)
348: {
349: struct timeval tv = { (time_t) (usec / 1000000), (long) (usec % 1000000) };
350:
351: return select(0, NULL, NULL, NULL, &tv);
352: }
1.3 misho 353:
354: /*
355: * e_innet() - Test address match in network
356: *
357: * @net = network
358: * @addr = address
359: * return: -1 error, 0 match or 1 not match
360: */
361: int
362: e_innet(netaddr_t * __restrict net, inaddr_t * __restrict addr)
363: {
364: register int i;
365: int ret = 0;
366:
367: if (!net || !addr)
368: return -1;
369:
370: switch (net->addr.sa.sa_family) {
371: case AF_INET:
372: for (i = 0; i < sizeof(struct in_addr); i++) {
373: ret = ((caddr_t) &net->addr.sin.sin_addr.s_addr)[i] &
374: net->mask.in.s4_addr[i];
375: ret -= addr->in.s4_addr[i] & net->mask.in.s4_addr[i];
376: if (ret)
377: break;
378: }
379: break;
380: case AF_INET6:
381: for (i = 0; i < sizeof(struct in6_addr); i++) {
382: ret = net->addr.sin6.sin6_addr.s6_addr[i] &
383: net->mask.in6.s6_addr[i];
384: ret -= addr->in6.s6_addr[i] & net->mask.in6.s6_addr[i];
385: if (ret)
386: break;
387: }
388: break;
389: default:
390: return -1;
391: }
392:
393: return !!ret;
394: }
1.4 misho 395:
396: /*
397: * e_getnet() - Get network from string
398: *
399: * @net = Network string (format: <net[/cidr]>)
400: * return: NULL error or !=NULL network should be e_free()
401: */
402: netaddr_t *
403: e_getnet(const char *net)
404: {
405: netaddr_t *n;
406: char *str, *wrk;
407: struct hostent *host;
408:
409: n = e_malloc(sizeof(netaddr_t));
410: if (!n) {
411: LOGERR;
412: return NULL;
413: } else
414: memset(n, 0, sizeof(netaddr_t));
415: str = e_strdup(net);
416: if (!str) {
417: LOGERR;
418: e_free(n);
419: return NULL;
420: }
421: wrk = strchr(str, '/');
422: if (wrk)
423: *wrk++ = 0;
424:
425: host = gethostbyname2(str, strchr(str, ':') ? AF_INET6 : AF_INET);
426: if (!host) {
427: elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
428: e_free(str);
429: e_free(n);
430: return NULL;
431: }
432: switch (host->h_addrtype) {
433: case AF_INET:
434: n->addr.sin.sin_len = sizeof(struct sockaddr_in);
435: n->addr.sin.sin_family = host->h_addrtype;
436: memcpy(&n->addr.sin.sin_addr, host->h_addr, sizeof n->addr.sin.sin_addr);
437: if (wrk)
438: n->mask.in.s_addr = E_CIDRMASK(strtol(wrk, NULL, 10));
439: else
440: n->mask.in.s_addr = 0xFFFFFFFF;
441: break;
442: case AF_INET6:
443: n->addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
444: n->addr.sin6.sin6_family = host->h_addrtype;
445: memcpy(&n->addr.sin6.sin6_addr, host->h_addr, sizeof n->addr.sin6.sin6_addr);
446: /* TODO: should support ipv6 mask */
447: break;
448: default:
449: elwix_SetErr(EINVAL, "Unsupported family #%d", host->h_addrtype);
450: e_free(str);
451: e_free(n);
452: return NULL;
453: }
454:
455: e_free(str);
456: return n;
457: }
1.7 misho 458:
459: /*
460: * e_ether_addr() - Get or set ethernet address from interface name
461: *
462: * @ifname = interface name
463: * @addr = if addr is !=NULL then set this for new address
1.10.10.2 misho 464: * return: NULL error or !=NULL get ethernet address should be e_free()
1.7 misho 465: */
466: ether_addr_t *
467: e_ether_addr(const char *ifname, ether_addr_t * __restrict addr)
468: {
469: ether_addr_t *a = NULL;
470: struct ifaddrs *p, *ifa = NULL;
471:
472: if (!ifname)
473: return NULL;
474:
475: a = e_malloc(sizeof(ether_addr_t));
476: if (!a)
477: return NULL;
478: else
479: memset(a, 0, sizeof(ether_addr_t));
480:
481: getifaddrs(&ifa);
482: for (p = ifa; p && p->ifa_name; p++)
483: if (p->ifa_name && !strcmp(p->ifa_name, ifname) && p->ifa_addr &&
484: p->ifa_addr->sa_family == AF_LINK) {
485: memcpy(a, LLADDR((struct sockaddr_dl*) p->ifa_addr), sizeof(ether_addr_t));
486: break;
487: }
488: freeifaddrs(ifa);
489:
490: return a;
491: }
1.10.10.1 misho 492:
493: /*
494: * e_get1stiface() - Get first interface of host
495: *
496: * @szIface = interface string buffer
497: * @iflen = size of interface buffer
498: * return: -1 error or 0 ok
499: */
500: int
501: e_get1stiface(char *szIface, int iflen)
502: {
503: struct ifaddrs *ifa;
504:
505: if (!szIface || !iflen)
506: return -1;
507:
508: getifaddrs(&ifa);
509: strlcpy(szIface, ifa->ifa_name, iflen);
510: freeifaddrs(ifa);
511: return 0;
512: }
1.10.10.3 misho 513:
514: /*
515: * e_getifacebyname() - Get interface and make network structure
516: *
517: * @psIface = Interface, if =NULL first interface
518: * @addr = Network address structure
519: * return: NULL error or !=NULL network structure
520: */
521: sockaddr_t *
522: e_getifacebyname(const char *psIface, sockaddr_t * __restrict addr)
523: {
524: char szIface[64] = { [0 ... 63] = 0 };
525: struct ifaddrs *p, *ifa = NULL;
526:
527: if (!addr)
528: return NULL;
529:
530: memset(addr, 0, sizeof(sockaddr_t));
531: getifaddrs(&ifa);
532: strlcpy(szIface, psIface ? psIface : ifa->ifa_name, sizeof szIface);
533: for (p = ifa; p && p->ifa_name; p++)
534: if (p->ifa_name && !strcmp(p->ifa_name, szIface) && p->ifa_addr &&
535: p->ifa_addr->sa_family == AF_LINK) {
536: memcpy(&addr->sdl, p->ifa_addr, sizeof(struct sockaddr_dl));
537: break;
538: }
539: freeifaddrs(ifa);
540:
541: return addr;
542: }
1.10.10.4 misho 543:
544: /*
545: * e_getlinkbyname() - Get host ethernet address and make network structure
546: *
547: * @psHost = Host ethernet address
548: * @addr = Network address structure
549: * return: NULL error or !=NULL network structure
550: */
551: sockaddr_t *
552: e_getlinkbyname(const char *psHost, sockaddr_t * __restrict addr)
553: {
1.10.10.6 misho 554: ait_val_t v;
555: sockaddr_t *a = addr;
556:
557: if (!psHost || !addr)
1.10.10.4 misho 558: return NULL;
559: else
560: memset(addr, 0, sizeof(sockaddr_t));
561:
1.10.10.6 misho 562: AIT_INIT_VAL2(&v, string);
563: if (!strchr(psHost, '.'))
564: AIT_SET_STR(&v, ":");
565: AIT_SET_STRCAT(&v, psHost);
566:
1.10.10.4 misho 567: addr->sdl.sdl_len = sizeof(struct sockaddr_dl);
1.10.10.6 misho 568: if (e_link_addr(AIT_GET_STR(&v), &addr->sdl))
569: a = NULL;
1.10.10.4 misho 570:
1.10.10.6 misho 571: AIT_FREE_VAL(&v);
572: return a;
1.10.10.4 misho 573: }
1.10.10.7! misho 574:
! 575: /*
! 576: * e_getlinkbyether() - Get ethernet address and make network structure
! 577: *
! 578: * @mac = Ethernet address
! 579: * @idx = Interface index
! 580: * @type = Interface type
! 581: * @iface = Interface name
! 582: * @addr = Network address structure
! 583: * return: NULL error or !=NULL network structure
! 584: */
! 585: sockaddr_t *
! 586: e_getlinkbyether(const ether_addr_t * __restrict mac, u_short idx, u_char type,
! 587: const char *iface, sockaddr_t * __restrict addr)
! 588: {
! 589: sockaddr_t *a = addr;
! 590:
! 591: if (!addr)
! 592: return NULL;
! 593: else
! 594: memset(addr, 0, sizeof(sockaddr_t));
! 595:
! 596: addr->sdl.sdl_len = sizeof(struct sockaddr_dl);
! 597: addr->sdl.sdl_family = AF_LINK;
! 598: addr->sdl.sdl_index = idx;
! 599: addr->sdl.sdl_type = type;
! 600: if (iface && *iface) {
! 601: addr->sdl.sdl_nlen = strlen(iface);
! 602: memcpy(addr->sdl.sdl_data, iface, addr->sdl.sdl_nlen);
! 603: }
! 604: addr->sdl.sdl_alen = sizeof(ether_addr_t);
! 605: memcpy(LLADDR(&addr->sdl), mac, addr->sdl.sdl_alen);
! 606:
! 607: return a;
! 608: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>