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