File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / net.c
Revision 1.19: download - view: text, annotated - select for diffs - revision graph
Wed Apr 4 01:25:26 2018 UTC (6 years, 7 months ago) by misho
Branches: MAIN
CVS tags: elwix4_21, elwix4_20, elwix4_19, elwix4_18, elwix4_17, elwix4_16, elwix4_15, elwix4_14, elwix4_13, elwix4_12, elwix4_11, HEAD, ELWIX4_20, ELWIX4_19, ELWIX4_18, ELWIX4_17, ELWIX4_16, ELWIX4_15, ELWIX4_14, ELWIX4_13, ELWIX4_12, ELWIX4_11, ELWIX4_10
version 4.10

    1: /*************************************************************************
    2: * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
    3: *  by Michael Pounov <misho@elwix.org>
    4: *
    5: * $Author: misho $
    6: * $Id: net.c,v 1.19 2018/04/04 01:25:26 misho Exp $
    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: 
   15: Copyright 2004 - 2018
   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: 
   49: #ifndef __linux__
   50: static char hexlist[] = "0123456789abcdef";
   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;
   70: 	int byte = 0, state = NAMING, new;
   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: 
  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++ = ':';
  162: 
  163: 		i = *in++;
  164: 		if (i > 0xf) {
  165: 			out[1] = hexlist[i & 0xf];
  166: 			i >>= 4;
  167: 		} else {
  168: 			out[1] = hexlist[i];
  169: 			i = 0;
  170: 		}
  171: 
  172: 		out[0] = hexlist[i];
  173: 		out += 2;
  174: 	}
  175: 
  176: 	*out = 0;
  177: 	return obuf;
  178: }
  179: 
  180: /*
  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: }
  198: #endif
  199: 
  200: /*
  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:  */
  208: char *
  209: e_ether_ntoa(const ether_addr_t * __restrict n, char * __restrict a, int len)
  210: {
  211: 	if (!n || !a)
  212: 		return NULL;
  213: 
  214: 	memset(a, 0, len);
  215: 	if (snprintf(a, len, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 
  216: 			n->octet[0], n->octet[1], 
  217: 			n->octet[2], n->octet[3], 
  218: 			n->octet[4], n->octet[5]) < 17)
  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:  */
  231: ether_addr_t *
  232: e_ether_aton(const char *a, ether_addr_t * __restrict e)
  233: {                       
  234: 	int i;
  235: 
  236: 	if (!a || !e)
  237: 		return NULL;
  238: 
  239: 	i = sscanf(a, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", 
  240: 			&e->octet[0], 
  241: 			&e->octet[1], 
  242: 			&e->octet[2], 
  243: 			&e->octet[3], 
  244: 			&e->octet[4], 
  245: 			&e->octet[5]);
  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:  */
  258: u_short
  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: {
  288: #ifndef __linux__
  289: 	char *s;
  290: #endif
  291: 	char str[INET6_ADDRSTRLEN] = { 0 };
  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;
  316: #ifndef __linux__
  317: 		case AF_LINK:
  318: 			if (!(s = e_link_ntoa(&addr->sdl))) {
  319: 				LOGERR;
  320: 				return ret;
  321: 			} else
  322: 				ret = s;
  323: 			break;
  324: #endif
  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
  341:  * return: 0 is error or >0 length of network structure
  342:  */
  343: socklen_t 
  344: e_gethostbyname(const char *psHost, u_short port, sockaddr_t * __restrict addr)
  345: {
  346: 	struct hostent *host = NULL;
  347: 
  348: 	if (!psHost || !addr)
  349: 		return 0;
  350: 
  351: 	if (*psHost != '/') {
  352: 		/* resolver */
  353: 		host = gethostbyname2(psHost, !strchr(psHost, ':') ? AF_INET : AF_INET6);
  354: 		if (!host) {
  355: 			elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
  356: 			return 0;
  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:
  369: #ifndef __linux__
  370: 			addr->sin.sin_len = sizeof(struct sockaddr_in);
  371: #endif
  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);
  375: 			return sizeof addr->sin;
  376: 		case AF_INET6:
  377: #ifndef __linux__
  378: 			addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
  379: #endif
  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);
  383: 			return sizeof addr->sin6;
  384: 		case AF_LOCAL:
  385: #ifndef __linux__
  386: 			addr->sun.sun_len = sizeof(struct sockaddr_un);
  387: #endif
  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);
  391: 			return sizeof addr->sun;
  392: 		default:
  393: 			elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
  394: 			break;
  395: 	}
  396: 
  397: 	return 0;
  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: 
  425: 	return E_SOCKADDR_MAX;
  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);
  455: #ifndef __linux__
  456: 			case AF_LINK:
  457: 				return memcmp(&a->sdl.sdl_data, &b->sdl.sdl_data, 
  458: 						sizeof a->sdl.sdl_data);
  459: #endif
  460: 			case AF_UNSPEC:
  461: 				return memcmp(a, b, sizeof(sockaddr_t));
  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:  */
  473: int
  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: }
  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] & 
  501: 					net->mask.in4.s4_addr[i];
  502: 				ret -= addr->in4.s4_addr[i] & net->mask.in4.s4_addr[i];
  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: }
  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:
  561: #ifndef __linux__
  562: 			n->addr.sin.sin_len = sizeof(struct sockaddr_in);
  563: #endif
  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);
  566: 			if (wrk && strtol(wrk, NULL, 10) != 32)
  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:
  572: #ifndef __linux__
  573: 			n->addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
  574: #endif
  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: }
  589: 
  590: /*
  591:  * e_ether_addr() - Get or set ethernet address from interface name
  592:  *
  593:  * @ifname = interface name
  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()
  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;
  602: 	struct ifreq req;
  603: 	int s;
  604: 	sockaddr_t sa = E_SOCKADDR_INIT;
  605: 
  606: 	memset(&req, 0, sizeof req);
  607: 	if (!ifname)
  608: 		return NULL;
  609: 
  610: 	getifaddrs(&ifa);
  611: 	for (p = ifa; p && p->ifa_name; p = p->ifa_next) {
  612: #ifndef __linux__
  613: 		if (p->ifa_name && !strcmp(p->ifa_name, ifname) && p->ifa_addr && 
  614: 				p->ifa_addr->sa_family == AF_LINK) {
  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: 			}
  630: 			break;
  631: 		}
  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: 	}
  658: 	freeifaddrs(ifa);
  659: 
  660: 	return a;
  661: }
  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: 
  684: #ifndef __linux__
  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);
  704: 	for (p = ifa; p && p->ifa_name; p = p->ifa_next)
  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: }
  780: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>