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