Annotation of libelwix/src/net.c, revision 1.21.18.1
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.21.18.1! misho 6: * $Id: net.c,v 1.21 2020/05/27 15:03:28 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.21.18.1! misho 15: Copyright 2004 - 2022
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.13 misho 49: #ifndef __linux__
1.6 misho 50: static char hexlist[] = "0123456789abcdef";
1.17 misho 51:
52: #ifndef HAVE_LINK_ADDR
53:
54: /* States*/
55: #define NAMING 0
56: #define GOTONE 1
57: #define GOTTWO 2
58: #define RESET 3
59: /* Inputs */
60: #define DIGIT (4*0)
61: #define END (4*1)
62: #define DELIM (4*2)
63: #define LETTER (4*3)
64:
65: void
66: link_addr(const char *addr, struct sockaddr_dl *sdl)
67: {
68: char *cp = sdl->sdl_data;
69: char *cplim = sdl->sdl_len + (char *)sdl;
1.20 misho 70: int byte = 0, state = NAMING, new = 0;
1.17 misho 71:
72: bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
73: sdl->sdl_family = AF_LINK;
74: do {
75: state &= ~LETTER;
76: if ((*addr >= '0') && (*addr <= '9')) {
77: new = *addr - '0';
78: } else if ((*addr >= 'a') && (*addr <= 'f')) {
79: new = *addr - 'a' + 10;
80: } else if ((*addr >= 'A') && (*addr <= 'F')) {
81: new = *addr - 'A' + 10;
82: } else if (*addr == 0) {
83: state |= END;
84: } else if (state == NAMING &&
85: (((*addr >= 'A') && (*addr <= 'Z')) ||
86: ((*addr >= 'a') && (*addr <= 'z'))))
87: state |= LETTER;
88: else
89: state |= DELIM;
90: addr++;
91: switch (state /* | INPUT */) {
92: case NAMING | DIGIT:
93: case NAMING | LETTER:
94: *cp++ = addr[-1];
95: continue;
96: case NAMING | DELIM:
97: state = RESET;
98: sdl->sdl_nlen = cp - sdl->sdl_data;
99: continue;
100: case GOTTWO | DIGIT:
101: *cp++ = byte;
102: /* FALLTHROUGH */
103: case RESET | DIGIT:
104: state = GOTONE;
105: byte = new;
106: continue;
107: case GOTONE | DIGIT:
108: state = GOTTWO;
109: byte = new + (byte << 4);
110: continue;
111: default: /* | DELIM */
112: state = RESET;
113: *cp++ = byte;
114: byte = 0;
115: continue;
116: case GOTONE | END:
117: case GOTTWO | END:
118: *cp++ = byte;
119: /* FALLTHROUGH */
120: case RESET | END:
121: break;
122: }
123: break;
124: } while (cp < cplim);
125: sdl->sdl_alen = cp - LLADDR(sdl);
126: new = cp - (char *)sdl;
127: if (new > sizeof(*sdl))
128: sdl->sdl_len = new;
129: return;
130: }
131: #endif
132:
1.6 misho 133:
134: /*
135: * e_link_ntoa() - String ethernet address from link address
136: *
137: * @sdl = link address
138: * return: =NULL error or !=NULL ethernet address, should be e_free()
139: */
140: char *
141: e_link_ntoa(const struct sockaddr_dl *sdl)
142: {
143: static char obuf[64];
144: char *out = obuf;
145: int i;
146: u_char *in = (u_char*) LLADDR(sdl);
147: u_char *inlim = in + sdl->sdl_alen;
148: int firsttime = 1;
149:
150: if (sdl->sdl_nlen) {
151: memcpy(obuf, sdl->sdl_data, sdl->sdl_nlen);
152: out += sdl->sdl_nlen;
153: if (sdl->sdl_alen)
154: *out++ = '!';
155: }
156:
157: while (in < inlim) {
158: if (firsttime)
159: firsttime ^= firsttime;
160: else
161: *out++ = ':';
1.8 misho 162:
1.6 misho 163: i = *in++;
164: if (i > 0xf) {
165: out[1] = hexlist[i & 0xf];
166: i >>= 4;
1.8 misho 167: } else {
168: out[1] = hexlist[i];
169: i = 0;
170: }
1.6 misho 171:
172: out[0] = hexlist[i];
173: out += 2;
174: }
175:
176: *out = 0;
177: return obuf;
178: }
179:
1.1 misho 180: /*
1.11 misho 181: * e_link_addr() - String ethernet address to link address
182: *
183: * @mac = ethernet address
184: * @sdl = link address
185: * return: -1 error or 0 ok
186: */
187: int
188: e_link_addr(const char *mac, struct sockaddr_dl * __restrict sdl)
189: {
190: if (!mac || !sdl)
191: return -1;
192: if (!sdl->sdl_len)
193: sdl->sdl_len = sizeof(struct sockaddr_dl);
194:
195: link_addr(mac, sdl);
196: return 0;
197: }
1.13 misho 198: #endif
1.11 misho 199:
200: /*
1.1 misho 201: * e_ether_ntoa() - Convert ethernet address to string
202: *
203: * @n = ethernet address structure, like struct ether_addr
204: * @a = string
205: * @len = string length
206: * return: NULL error or !=NULL string a
207: */
1.2 misho 208: char *
1.7 misho 209: e_ether_ntoa(const ether_addr_t * __restrict n, char * __restrict a, int len)
1.1 misho 210: {
211: if (!n || !a)
212: return NULL;
213:
214: memset(a, 0, len);
1.8 misho 215: if (snprintf(a, len, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1.11 misho 216: n->octet[0], n->octet[1],
217: n->octet[2], n->octet[3],
218: n->octet[4], n->octet[5]) < 17)
1.1 misho 219: return NULL;
220:
221: return a;
222: }
223:
224: /*
225: * e_ether_aton() - Convert string to ethernet address
226: *
227: * @a = string
228: * @e = ethernet address structure, like struct ether_addr
229: * return: NULL error or !=NULL ethernet address structure
230: */
1.7 misho 231: ether_addr_t *
232: e_ether_aton(const char *a, ether_addr_t * __restrict e)
1.1 misho 233: {
234: int i;
235:
236: if (!a || !e)
237: return NULL;
238:
1.8 misho 239: i = sscanf(a, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
1.11 misho 240: &e->octet[0],
241: &e->octet[1],
242: &e->octet[2],
243: &e->octet[3],
244: &e->octet[4],
245: &e->octet[5]);
1.1 misho 246: if (i != 6)
247: return NULL;
248:
249: return e;
250: }
251:
252: /*
253: * e_n2port() - Extract port from network structure
254: *
255: * @addr = Address
256: * return: 0 not supported family type or port number
257: */
1.2 misho 258: u_short
1.1 misho 259: e_n2port(sockaddr_t * __restrict addr)
260: {
261: u_short port = 0;
262:
263: if (!addr)
264: return port;
265:
266: switch (addr->sa.sa_family) {
267: case AF_INET:
268: return ntohs(addr->sin.sin_port);
269: case AF_INET6:
270: return ntohs(addr->sin6.sin6_port);
271: default:
272: break;
273: }
274:
275: return port;
276: }
277:
278: /*
279: * e_n2addr() - Extract address from network structure
280: *
281: * @addr = Address
282: * @val = Value for store string address
283: * return: NULL error or !=NULL string address from val
284: */
285: const char *
286: e_n2addr(sockaddr_t * __restrict addr, ait_val_t * __restrict val)
287: {
1.13 misho 288: #ifndef __linux__
289: char *s;
290: #endif
291: char str[INET6_ADDRSTRLEN] = { 0 };
1.1 misho 292: const char *ret = NULL;
293:
294: if (!addr || !val)
295: return ret;
296:
297: AIT_INIT_VAL(val);
298: switch (addr->sa.sa_family) {
299: case AF_INET:
300: if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
301: LOGERR;
302: return ret;
303: } else
304: ret = str;
305: break;
306: case AF_INET6:
307: if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
308: LOGERR;
309: return ret;
310: } else
311: ret = str;
312: break;
313: case AF_LOCAL:
314: ret = addr->sun.sun_path;
315: break;
1.13 misho 316: #ifndef __linux__
1.5 misho 317: case AF_LINK:
1.6 misho 318: if (!(s = e_link_ntoa(&addr->sdl))) {
1.5 misho 319: LOGERR;
320: return ret;
321: } else
322: ret = s;
323: break;
1.13 misho 324: #endif
1.1 misho 325: default:
326: elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
327: addr->sa.sa_family);
328: return ret;
329: }
330:
331: AIT_SET_STR(val, ret);
332: return (const char*) AIT_GET_STR(val);
333: }
334:
335: /*
336: * e_gethostbyname() - Get host and port and make network structure
337: *
338: * @psHost = Hostname
339: * @port = Port
340: * @addr = Network address structure
1.15 misho 341: * return: 0 is error or >0 length of network structure
1.1 misho 342: */
1.14 misho 343: socklen_t
1.1 misho 344: e_gethostbyname(const char *psHost, u_short port, sockaddr_t * __restrict addr)
345: {
346: struct hostent *host = NULL;
347:
348: if (!psHost || !addr)
1.14 misho 349: return 0;
1.1 misho 350:
351: if (*psHost != '/') {
352: /* resolver */
1.10 misho 353: host = gethostbyname2(psHost, !strchr(psHost, ':') ? AF_INET : AF_INET6);
1.1 misho 354: if (!host) {
355: elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
1.14 misho 356: return 0;
1.1 misho 357: } else {
358: memset(addr, 0, sizeof(sockaddr_t));
359: addr->sa.sa_family = host->h_addrtype;
360: }
361: } else {
362: memset(addr, 0, sizeof(sockaddr_t));
363: addr->sa.sa_family = AF_LOCAL;
364: }
365:
366:
367: switch (addr->sa.sa_family) {
368: case AF_INET:
1.13 misho 369: #ifndef __linux__
1.1 misho 370: addr->sin.sin_len = sizeof(struct sockaddr_in);
1.13 misho 371: #endif
1.1 misho 372: addr->sin.sin_family = AF_INET;
373: addr->sin.sin_port = htons(port);
374: memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
1.14 misho 375: return sizeof addr->sin;
1.1 misho 376: case AF_INET6:
1.13 misho 377: #ifndef __linux__
1.1 misho 378: addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
1.13 misho 379: #endif
1.1 misho 380: addr->sin6.sin6_family = AF_INET6;
381: addr->sin6.sin6_port = htons(port);
382: memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
1.14 misho 383: return sizeof addr->sin6;
1.1 misho 384: case AF_LOCAL:
1.13 misho 385: #ifndef __linux__
1.1 misho 386: addr->sun.sun_len = sizeof(struct sockaddr_un);
1.13 misho 387: #endif
1.1 misho 388: addr->sun.sun_family = AF_LOCAL;
389: memset(addr->sun.sun_path, 0, sizeof addr->sun.sun_path);
390: snprintf(addr->sun.sun_path, sizeof addr->sun.sun_path, "%s-%hu", psHost, port);
1.14 misho 391: return sizeof addr->sun;
1.1 misho 392: default:
393: elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
394: break;
395: }
396:
1.14 misho 397: return 0;
1.15 misho 398: }
399:
400: /*
401: * e_addrlen() - Get address length from network structure
402: *
403: * @addr = address
404: * return: 0 is error or >0 length of network structure
405: */
406: socklen_t
407: e_addrlen(const sockaddr_t *addr)
408: {
409: if (!addr)
410: return 0;
411:
412: switch (addr->sa.sa_family) {
413: case AF_INET:
414: return sizeof addr->sin;
415: case AF_INET6:
416: return sizeof addr->sin6;
417: case AF_LOCAL:
418: return sizeof addr->sun;
419: #ifndef __linux__
420: case AF_LINK:
421: return sizeof addr->sdl;
422: #endif
423: }
424:
1.16 misho 425: return E_SOCKADDR_MAX;
1.1 misho 426: }
427:
428: /*
429: * e_addrcmp() - Compare network addresses
430: *
431: * @a = 1st address
432: * @b = 2nd address
433: * @p = compare and ports, if family is AF_INET or AF_INET6
434: * return: 0 is equal or !=0 is different
435: */
436: int
437: e_addrcmp(sockaddr_t * __restrict a, sockaddr_t * __restrict b, int p)
438: {
439: if (a && b && a->sa.sa_family == b->sa.sa_family)
440: switch (a->sa.sa_family) {
441: case AF_LOCAL:
442: return strcmp(a->sun.sun_path, b->sun.sun_path);
443: case AF_INET:
444: if (p && (a->sin.sin_port - b->sin.sin_port))
445: return (int) !!(a->sin.sin_port - b->sin.sin_port);
446: else
447: return memcmp(&a->sin.sin_addr, &b->sin.sin_addr,
448: sizeof a->sin.sin_addr);
449: case AF_INET6:
450: if (p && (a->sin6.sin6_port - b->sin6.sin6_port))
451: return (int) !!(a->sin6.sin6_port - b->sin6.sin6_port);
452: else
453: return memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr,
454: sizeof a->sin6.sin6_addr);
1.13 misho 455: #ifndef __linux__
1.1 misho 456: case AF_LINK:
457: return memcmp(&a->sdl.sdl_data, &b->sdl.sdl_data,
458: sizeof a->sdl.sdl_data);
1.13 misho 459: #endif
1.11 misho 460: case AF_UNSPEC:
461: return memcmp(a, b, sizeof(sockaddr_t));
1.1 misho 462: }
463:
464: return (int) !!(a - b);
465: }
466:
467: /*
468: * e_usleep() - usleep() replacement for ELWIX
469: *
470: * @usec = microseconds for sleep
471: * return: -1 interrupted by signal or 0 ok
472: */
1.2 misho 473: int
1.1 misho 474: e_usleep(u_int usec)
475: {
476: struct timeval tv = { (time_t) (usec / 1000000), (long) (usec % 1000000) };
477:
478: return select(0, NULL, NULL, NULL, &tv);
479: }
1.3 misho 480:
481: /*
482: * e_innet() - Test address match in network
483: *
484: * @net = network
485: * @addr = address
486: * return: -1 error, 0 match or 1 not match
487: */
488: int
489: e_innet(netaddr_t * __restrict net, inaddr_t * __restrict addr)
490: {
491: register int i;
492: int ret = 0;
493:
494: if (!net || !addr)
495: return -1;
496:
497: switch (net->addr.sa.sa_family) {
498: case AF_INET:
499: for (i = 0; i < sizeof(struct in_addr); i++) {
500: ret = ((caddr_t) &net->addr.sin.sin_addr.s_addr)[i] &
1.19 misho 501: net->mask.in4.s4_addr[i];
502: ret -= addr->in4.s4_addr[i] & net->mask.in4.s4_addr[i];
1.3 misho 503: if (ret)
504: break;
505: }
506: break;
507: case AF_INET6:
508: for (i = 0; i < sizeof(struct in6_addr); i++) {
509: ret = net->addr.sin6.sin6_addr.s6_addr[i] &
510: net->mask.in6.s6_addr[i];
511: ret -= addr->in6.s6_addr[i] & net->mask.in6.s6_addr[i];
512: if (ret)
513: break;
514: }
515: break;
516: default:
517: return -1;
518: }
519:
520: return !!ret;
521: }
1.4 misho 522:
523: /*
524: * e_getnet() - Get network from string
525: *
526: * @net = Network string (format: <net[/cidr]>)
527: * return: NULL error or !=NULL network should be e_free()
528: */
529: netaddr_t *
530: e_getnet(const char *net)
531: {
532: netaddr_t *n;
533: char *str, *wrk;
534: struct hostent *host;
535:
536: n = e_malloc(sizeof(netaddr_t));
537: if (!n) {
538: LOGERR;
539: return NULL;
540: } else
541: memset(n, 0, sizeof(netaddr_t));
542: str = e_strdup(net);
543: if (!str) {
544: LOGERR;
545: e_free(n);
546: return NULL;
547: }
548: wrk = strchr(str, '/');
549: if (wrk)
550: *wrk++ = 0;
551:
552: host = gethostbyname2(str, strchr(str, ':') ? AF_INET6 : AF_INET);
553: if (!host) {
554: elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
555: e_free(str);
556: e_free(n);
557: return NULL;
558: }
559: switch (host->h_addrtype) {
560: case AF_INET:
1.13 misho 561: #ifndef __linux__
1.4 misho 562: n->addr.sin.sin_len = sizeof(struct sockaddr_in);
1.13 misho 563: #endif
1.4 misho 564: n->addr.sin.sin_family = host->h_addrtype;
565: memcpy(&n->addr.sin.sin_addr, host->h_addr, sizeof n->addr.sin.sin_addr);
1.18 misho 566: if (wrk && strtol(wrk, NULL, 10) != 32)
1.4 misho 567: n->mask.in.s_addr = E_CIDRMASK(strtol(wrk, NULL, 10));
568: else
569: n->mask.in.s_addr = 0xFFFFFFFF;
570: break;
571: case AF_INET6:
1.13 misho 572: #ifndef __linux__
1.4 misho 573: n->addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
1.13 misho 574: #endif
1.4 misho 575: n->addr.sin6.sin6_family = host->h_addrtype;
576: memcpy(&n->addr.sin6.sin6_addr, host->h_addr, sizeof n->addr.sin6.sin6_addr);
577: /* TODO: should support ipv6 mask */
578: break;
579: default:
580: elwix_SetErr(EINVAL, "Unsupported family #%d", host->h_addrtype);
581: e_free(str);
582: e_free(n);
583: return NULL;
584: }
585:
586: e_free(str);
587: return n;
588: }
1.7 misho 589:
590: /*
591: * e_ether_addr() - Get or set ethernet address from interface name
592: *
593: * @ifname = interface name
1.13 misho 594: * @addr = if addr is !=NULL then set new ethernet address
595: * return: NULL error or !=NULL get current ethernet address should be e_free()
1.7 misho 596: */
597: ether_addr_t *
598: e_ether_addr(const char *ifname, ether_addr_t * __restrict addr)
599: {
600: ether_addr_t *a = NULL;
601: struct ifaddrs *p, *ifa = NULL;
1.13 misho 602: struct ifreq req;
603: int s;
604: sockaddr_t sa = E_SOCKADDR_INIT;
1.7 misho 605:
1.13 misho 606: memset(&req, 0, sizeof req);
1.7 misho 607: if (!ifname)
608: return NULL;
609:
610: getifaddrs(&ifa);
1.13 misho 611: for (p = ifa; p && p->ifa_name; p = p->ifa_next) {
612: #ifndef __linux__
1.7 misho 613: if (p->ifa_name && !strcmp(p->ifa_name, ifname) && p->ifa_addr &&
614: p->ifa_addr->sa_family == AF_LINK) {
1.13 misho 615: a = e_malloc(sizeof(ether_addr_t));
616: if (a)
617: memcpy(a, LLADDR((struct sockaddr_dl*) p->ifa_addr),
618: sizeof(ether_addr_t));
619:
620: /* should set mac address */
621: if (addr && (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) > 0) {
622: strlcpy(req.ifr_name, ifname, sizeof req.ifr_name);
623: sa.sa.sa_family = AF_LINK;
624: sa.sa.sa_len = sizeof(ether_addr_t);
625: memcpy(sa.sa.sa_data, addr, sizeof(ether_addr_t));
626: req.ifr_ifru.ifru_addr = sa.sa;
627: ioctl(s, SIOCSIFLLADDR, &req);
628: close(s);
629: }
1.7 misho 630: break;
631: }
1.13 misho 632: #else
633: if (p->ifa_name && !strcmp(p->ifa_name, ifname)) {
634: s = socket(AF_INET, SOCK_DGRAM, 0);
635: if (s == -1)
636: break;
637: strlcpy(req.ifr_name, ifname, sizeof req.ifr_name);
638: if (!ioctl(s, SIOCGIFHWADDR, &req)) {
639: a = e_malloc(sizeof(ether_addr_t));
640: if (a)
641: memcpy(a, req.ifr_addr.sa_data, sizeof(ether_addr_t));
642:
643: /* should set mac address */
644: if (addr) {
645: memset(&req, 0, sizeof req);
646: strlcpy(req.ifr_name, ifname, sizeof req.ifr_name);
647: sa.sa.sa_family = ARPHRD_ETHER;
648: memcpy(sa.sa.sa_data, addr, sizeof(ether_addr_t));
649: req.ifr_hwaddr = sa.sa;
650: ioctl(s, SIOCSIFHWADDR, &req);
651: }
652: }
653: close(s);
654: break;
655: }
656: #endif
657: }
1.7 misho 658: freeifaddrs(ifa);
659:
660: return a;
661: }
1.11 misho 662:
663: /*
664: * e_get1stiface() - Get first interface of host
665: *
666: * @szIface = interface string buffer
667: * @iflen = size of interface buffer
668: * return: -1 error or 0 ok
669: */
670: int
671: e_get1stiface(char *szIface, int iflen)
672: {
673: struct ifaddrs *ifa;
674:
675: if (!szIface || !iflen)
676: return -1;
677:
678: getifaddrs(&ifa);
679: strlcpy(szIface, ifa->ifa_name, iflen);
680: freeifaddrs(ifa);
681: return 0;
682: }
683:
1.13 misho 684: #ifndef __linux__
1.11 misho 685: /*
686: * e_getifacebyname() - Get interface and make network structure
687: *
688: * @psIface = Interface, if =NULL first interface
689: * @addr = Network address structure
690: * return: NULL error or !=NULL network structure
691: */
692: sockaddr_t *
693: e_getifacebyname(const char *psIface, sockaddr_t * __restrict addr)
694: {
695: char szIface[64] = { [0 ... 63] = 0 };
696: struct ifaddrs *p, *ifa = NULL;
697:
698: if (!addr)
699: return NULL;
700:
701: memset(addr, 0, sizeof(sockaddr_t));
702: getifaddrs(&ifa);
703: strlcpy(szIface, psIface ? psIface : ifa->ifa_name, sizeof szIface);
1.13 misho 704: for (p = ifa; p && p->ifa_name; p = p->ifa_next)
1.11 misho 705: if (p->ifa_name && !strcmp(p->ifa_name, szIface) && p->ifa_addr &&
706: p->ifa_addr->sa_family == AF_LINK) {
707: memcpy(&addr->sdl, p->ifa_addr, sizeof(struct sockaddr_dl));
708: break;
709: }
710: freeifaddrs(ifa);
711:
712: return addr;
713: }
714:
715: /*
716: * e_getlinkbyname() - Get host ethernet address and make network structure
717: *
718: * @psHost = Host ethernet address
719: * @addr = Network address structure
720: * return: NULL error or !=NULL network structure
721: */
722: sockaddr_t *
723: e_getlinkbyname(const char *psHost, sockaddr_t * __restrict addr)
724: {
725: ait_val_t v;
726: sockaddr_t *a = addr;
727:
728: if (!psHost || !addr)
729: return NULL;
730: else
731: memset(addr, 0, sizeof(sockaddr_t));
732:
733: AIT_INIT_VAL2(&v, string);
734: if (!strchr(psHost, '.'))
735: AIT_SET_STR(&v, ":");
736: AIT_SET_STRCAT(&v, psHost);
737:
738: addr->sdl.sdl_len = sizeof(struct sockaddr_dl);
739: if (e_link_addr(AIT_GET_STR(&v), &addr->sdl))
740: a = NULL;
741:
742: AIT_FREE_VAL(&v);
743: return a;
744: }
745:
746: /*
747: * e_getlinkbyether() - Get ethernet address and make network structure
748: *
749: * @mac = Ethernet address
750: * @idx = Interface index
751: * @type = Interface type
752: * @iface = Interface name
753: * @addr = Network address structure
754: * return: NULL error or !=NULL network structure
755: */
756: sockaddr_t *
757: e_getlinkbyether(const ether_addr_t * __restrict mac, u_short idx, u_char type,
758: const char *iface, sockaddr_t * __restrict addr)
759: {
760: sockaddr_t *a = addr;
761:
762: if (!addr)
763: return NULL;
764: else
765: memset(addr, 0, sizeof(sockaddr_t));
766:
767: addr->sdl.sdl_len = sizeof(struct sockaddr_dl);
768: addr->sdl.sdl_family = AF_LINK;
769: addr->sdl.sdl_index = idx;
770: addr->sdl.sdl_type = type;
771: if (iface && *iface) {
772: addr->sdl.sdl_nlen = strlen(iface);
773: memcpy(addr->sdl.sdl_data, iface, addr->sdl.sdl_nlen);
774: }
775: addr->sdl.sdl_alen = sizeof(ether_addr_t);
776: memcpy(LLADDR(&addr->sdl), mac, addr->sdl.sdl_alen);
777:
778: return a;
779: }
1.13 misho 780: #endif
1.21 misho 781:
782: /*
783: * e_network() - Get network from address string
784: *
785: * @csAddr = Address string with CIDR mask /xx
786: * @net = Network information structure
787: * return: -1 error, 1 nothing for return or 0 ok
788: */
789: int
790: e_network(const char *csAddr, netaddr_t * __restrict net)
791: {
792: int ret = 0;
793: u_char mask = 0;
794: inaddr_t a;
795: char *pos, szAddr[STRSIZ];
796: register int i;
797:
798: if (!csAddr || !net)
799: return -1;
800: else
801: strlcpy(szAddr, csAddr, sizeof szAddr);
802:
803: memset(net, 0, sizeof(netaddr_t));
804:
805: pos = strrchr(szAddr, '/');
806: if (pos) {
807: *pos++ = 0;
808: mask = (u_char) strtol(pos, NULL, 10);
809: } else
810: return 1;
811:
812: if (strchr(szAddr, ':')) {
813: if (mask > 128)
814: return -1;
815: else {
1.21.18.1! misho 816: #ifndef __linux__
1.21 misho 817: for (i = 0; i < 4 && (mask / 32); i++, mask -= 32)
818: net->mask.in6.__u6_addr.__u6_addr32[i] = 0xFFFFFFFF;
819: if (mask)
820: net->mask.in6.__u6_addr.__u6_addr32[i] = E_CIDRMASK(mask % 32);
1.21.18.1! misho 821: #else
! 822: for (i = 0; i < 4 && (mask / 32); i++, mask -= 32)
! 823: net->mask.in6.__in6_u.__u6_addr32[i] = 0xFFFFFFFF;
! 824: if (mask)
! 825: net->mask.in6.__in6_u.__u6_addr32[i] = E_CIDRMASK(mask % 32);
! 826: #endif
1.21 misho 827: }
828:
829: inet_pton(AF_INET6, szAddr, &a.in6);
830:
831: #ifndef __linux__
832: net->addr.sin6.sin6_len = sizeof net->addr.sin6;
833: for (i = 0; i < 4; i++)
834: net->addr.sin6.sin6_addr.__u6_addr.__u6_addr32[i] =
835: a.in6.__u6_addr.__u6_addr32[i] & net->mask.in6.__u6_addr.__u6_addr32[i];
1.21.18.1! misho 836: #else
! 837: for (i = 0; i < 4; i++)
! 838: net->addr.sin6.sin6_addr.__in6_u.__u6_addr32[i] =
! 839: a.in6.__in6_u.__u6_addr32[i] & net->mask.in6.__in6_u.__u6_addr32[i];
! 840: #endif
1.21 misho 841: } else {
842: if (mask > 32)
843: return -1;
844: else {
845: if (mask == 32)
846: net->mask.in.s_addr = 0xFFFFFFFF;
847: else
848: net->mask.in.s_addr = E_CIDRMASK(mask);
849: }
850:
851: inet_pton(AF_INET, szAddr, &a.in4);
852:
853: #ifndef __linux__
854: net->addr.sin.sin_len = sizeof net->addr.sin;
855: #endif
856: net->addr.sin.sin_addr.s_addr = a.in.s_addr & net->mask.in.s_addr;
857: }
858:
859: return ret;
860: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>