File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libpdel / net / if_iface.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:25:53 2012 UTC (13 years, 4 months ago) by misho
Branches: libpdel, MAIN
CVS tags: v0_5_3, HEAD
libpdel

    1: 
    2: /*
    3:  * Copyright (c) 2001-2002 Packet Design, LLC.
    4:  * All rights reserved.
    5:  * 
    6:  * Subject to the following obligations and disclaimer of warranty,
    7:  * use and redistribution of this software, in source or object code
    8:  * forms, with or without modifications are expressly permitted by
    9:  * Packet Design; provided, however, that:
   10:  * 
   11:  *    (i)  Any and all reproductions of the source or object code
   12:  *         must include the copyright notice above and the following
   13:  *         disclaimer of warranties; and
   14:  *    (ii) No rights are granted, in any manner or form, to use
   15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
   16:  *         on advertising, endorsements, or otherwise except as such
   17:  *         appears in the above copyright notice or in the software.
   18:  * 
   19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
   20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
   21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
   22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
   23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
   24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
   25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
   26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
   27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
   28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
   29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
   30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
   31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
   32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
   33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
   35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
   36:  * THE POSSIBILITY OF SUCH DAMAGE.
   37:  *
   38:  * Author: Archie Cobbs <archie@freebsd.org>
   39:  */
   40: 
   41: #include <sys/types.h>
   42: #include <sys/param.h>
   43: #include <sys/socket.h>
   44: #include <sys/sysctl.h>
   45: #include <sys/sockio.h>
   46: 
   47: #include <net/if.h>
   48: #include <net/if_dl.h>
   49: #include <net/route.h>
   50: 
   51: #include <netinet/in.h>
   52: #include <arpa/inet.h>
   53: 
   54: #include <stdio.h>
   55: #include <stdlib.h>
   56: #include <stdarg.h>
   57: #include <unistd.h>
   58: #include <string.h>
   59: #include <errno.h>
   60: #include <err.h>
   61: 
   62: #include "structs/structs.h"
   63: #include "structs/type/array.h"
   64: 
   65: #include "util/typed_mem.h"
   66: #include "net/if_util.h"
   67: 
   68: #define ROUNDUP(a) \
   69: 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
   70: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
   71: 
   72: static struct	if_msghdr *if_find(const char *ifname,
   73: 			u_char **bufp, const char *mtype);
   74: static int	if_info(u_char **bufp, const char *mtype);
   75: 
   76: /*
   77:  * Get list of IP addresses and netmasks configured on an interface.
   78:  */
   79: int
   80: if_get_ip_addrs(const char *ifname, struct in_addr **iplistp,
   81: 	struct in_addr **nmlistp, const char *mtype)
   82: {
   83: 	struct if_msghdr *ifm;
   84: 	struct ifa_msghdr *ifam;
   85: 	struct in_addr *iplist = NULL;
   86: 	struct in_addr *nmlist = NULL;
   87: 	int errno_save;
   88: 	int num = 0;
   89: 	u_char *buf;
   90: 
   91: 	/* Find interface info */
   92: 	if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
   93: 		return (-1);
   94: 
   95: 	/* Search for first IP address */
   96: 	for (ifam = (struct ifa_msghdr *)(void *)
   97: 	      ((u_char *)ifm + ifm->ifm_msglen);
   98: 	    ifam->ifam_type == RTM_NEWADDR;
   99: 	    ifam = (struct ifa_msghdr *)(void *)
  100: 	      ((u_char *)ifam + ifam->ifam_msglen))
  101: 		num++;
  102: 
  103: 	/* Allocate arrays */
  104: 	if ((iplist = MALLOC(mtype, num * sizeof(*iplist))) == NULL
  105: 	    || (nmlist = MALLOC(mtype, num * sizeof(*nmlist))) == NULL) {
  106: 		errno_save = errno;
  107: 		FREE(mtype, iplist);				/* ok if NULL */
  108: 		FREE(TYPED_MEM_TEMP, buf);
  109: 		errno = errno_save;
  110: 		return (-1);
  111: 	}
  112: 
  113: 	/* Search for IP address/netmask combinations */
  114: 	num = 0;
  115: 	for (ifam = (struct ifa_msghdr *)(void *)
  116: 	     ((u_char *)ifm + ifm->ifm_msglen);
  117: 	    ifam->ifam_type == RTM_NEWADDR;
  118: 	    ifam = (struct ifa_msghdr *)(void *)
  119: 	      ((u_char *)ifam + ifam->ifam_msglen)) {
  120: 		char *cp = (char *)(ifam + 1);
  121: 		int need = RTA_IFA | RTA_NETMASK;
  122: 		int i;
  123: 
  124: 		/* Find IP address and netmask, if any */
  125: 		if ((ifam->ifam_addrs & need) != need)
  126: 			continue;
  127: 		for (i = 1; i != 0 && need != 0; i <<= 1) {
  128: 			if ((ifam->ifam_addrs & i) == 0)
  129: 				continue;
  130: 			if (i == RTA_IFA
  131: 			    && ((struct sockaddr *)(void *)cp)->sa_family
  132: 			      == AF_INET) {
  133: 				iplist[num] = ((struct sockaddr_in *)
  134: 				    (void *)cp)->sin_addr;
  135: 			} else if (i == RTA_NETMASK) {
  136: 				nmlist[num] = ((struct sockaddr_in *)
  137: 				    (void *)cp)->sin_addr;
  138: 			}
  139: 			need &= ~i;
  140: 			ADVANCE(cp, (struct sockaddr *)cp);
  141: 		}
  142: 		if (need == 0)
  143: 			num++;
  144: 	}
  145: 
  146: 	/* Done */
  147: 	FREE(TYPED_MEM_TEMP, buf);
  148: 	*iplistp = iplist;
  149: 	*nmlistp = nmlist;
  150: 	return (num);
  151: }
  152: 
  153: /*
  154:  * Get the first IP address on an interface.
  155:  */
  156: int
  157: if_get_ip_addr(const char *ifname, struct in_addr *ipp, struct in_addr *nmp)
  158: {
  159: 	struct in_addr *iplist;
  160: 	struct in_addr *nmlist;
  161: 	int nip;
  162: 
  163: 	if ((nip = if_get_ip_addrs(ifname,
  164: 	    &iplist, &nmlist, TYPED_MEM_TEMP)) == -1)
  165: 		return (-1);
  166: 	if (nip == 0) {
  167: 		FREE(TYPED_MEM_TEMP, iplist);
  168: 		FREE(TYPED_MEM_TEMP, nmlist);
  169: 		errno = ENOENT;
  170: 		return (-1);
  171: 	}
  172: 	if (ipp != NULL)
  173: 		*ipp = iplist[0];
  174: 	if (nmp != NULL)
  175: 		*nmp = nmlist[0];
  176: 	FREE(TYPED_MEM_TEMP, iplist);
  177: 	FREE(TYPED_MEM_TEMP, nmlist);
  178: 	return (0);
  179: }
  180: 
  181: /*
  182:  * Get the flags associated with an interface.
  183:  */
  184: int
  185: if_get_flags(const char *ifname)
  186: {
  187: 	struct if_msghdr *ifm;
  188: 	u_char *buf;
  189: 	int rtn;
  190: 
  191: 	if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
  192: 		return (-1);
  193: 	rtn = ifm->ifm_flags;
  194: 	FREE(TYPED_MEM_TEMP, buf);
  195: 	return (rtn);
  196: }
  197: 
  198: /*
  199:  * Set the flags associated with an interface.
  200:  */
  201: int
  202: if_set_flags(const char *ifname, int flags)
  203: {
  204: 	struct ifreq ifr;
  205: 	int r;
  206: 	int s;
  207: 
  208: 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
  209: 		return (-1);
  210: 	memset(&ifr, 0, sizeof(ifr));
  211: 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
  212: 	ifr.ifr_flags = flags;
  213: 	r = ioctl(s, SIOCSIFFLAGS, (char *)&ifr);
  214: 	(void)close(s);
  215: 	return (r);
  216: }
  217: 
  218: /*
  219:  * Get the MTU associated with an interface.
  220:  */
  221: int
  222: if_get_mtu(const char *ifname)
  223: {
  224: 	struct if_msghdr *ifm;
  225: 	u_char *buf;
  226: 	int rtn;
  227: 
  228: 	if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
  229: 		return (-1);
  230: 	rtn = ifm->ifm_data.ifi_mtu;
  231: 	FREE(TYPED_MEM_TEMP, buf);
  232: 	return (rtn);
  233: }
  234: 
  235: /*
  236:  * Set the MTU associated with an interface.
  237:  */
  238: int
  239: if_set_mtu(const char *ifname, u_int mtu)
  240: {
  241: 	struct ifreq ifr;
  242: 	int r;
  243: 	int s;
  244: 
  245: 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
  246: 		return (-1);
  247: 	memset(&ifr, 0, sizeof(ifr));
  248: 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
  249: 	ifr.ifr_mtu = mtu;
  250: 	r = ioctl(s, SIOCSIFMTU, (char *)&ifr);
  251: 	(void)close(s);
  252: 	return (r);
  253: }
  254: 
  255: /*
  256:  * Get the interface type.
  257:  */
  258: int
  259: if_get_type(const char *ifname)
  260: {
  261: 	struct if_msghdr *ifm;
  262: 	u_char *buf;
  263: 	int rtn;
  264: 
  265: 	if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
  266: 		return (-1);
  267: 	rtn = ifm->ifm_data.ifi_type;
  268: 	FREE(TYPED_MEM_TEMP, buf);
  269: 	return (rtn);
  270: }
  271: 
  272: /*
  273:  * Get the link address for an interface.
  274:  */
  275: int
  276: if_get_link_addr(const char *ifname,
  277: 	struct sockaddr_dl **sdlp, const char *mtype)
  278: {
  279: 	struct if_msghdr *ifm;
  280: 	struct sockaddr_dl *sdl;
  281: 	int errno_save;
  282: 	u_char *buf;
  283: 
  284: 	if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
  285: 		return (-1);
  286: 	sdl = (struct sockaddr_dl *)(ifm + 1);
  287: 	if ((*sdlp = MALLOC(mtype, sdl->sdl_len)) == NULL) {
  288: 		errno_save = errno;
  289: 		FREE(TYPED_MEM_TEMP, buf);
  290: 		errno = errno_save;
  291: 		return (-1);
  292: 	}
  293: 	memcpy(*sdlp, sdl, sdl->sdl_len);
  294: 	FREE(TYPED_MEM_TEMP, buf);
  295: 	return (0);
  296: }
  297: 
  298: /*
  299:  * Gets the names of all system interfaces.
  300:  */
  301: int
  302: if_get_list(char ***listp, const char *mtype)
  303: {
  304: 	char **list = NULL;
  305: 	int errno_save;
  306: 	int num = 0;
  307: 	u_char *buf;
  308: 	u_char *ptr;
  309: 	int len;
  310: 
  311: 	/* Get raw data from kernel */
  312: 	if ((len = if_info(&buf, TYPED_MEM_TEMP)) == -1)
  313: 		return (-1);
  314: 
  315: 	/* Scan interfaces */
  316: 	for (ptr = buf;
  317: 	    ptr < buf + len;
  318: 	    ptr += ((struct if_msghdr *)(void *)ptr)->ifm_msglen) {
  319: 		struct if_msghdr *const ifm = (struct if_msghdr *)(void *)ptr;
  320: 
  321: 		/* Sanity check version */
  322: 		if (ifm->ifm_version != RTM_VERSION) {
  323: 			errno = EIO;
  324: 			goto fail;
  325: 		}
  326: 
  327: 		/* Next interface? */
  328: 		if (ifm->ifm_type == RTM_IFINFO) {
  329: 			struct sockaddr_dl *const sdl
  330: 			    = (struct sockaddr_dl *)(ifm + 1);
  331: 			char nbuf[IF_NAMESIZE + 1];
  332: 			void *new_list;
  333: 
  334: 			/* Get name */
  335: 			if (sdl->sdl_nlen > sizeof(nbuf) - 1)
  336: 				continue;
  337: 			memcpy(nbuf, sdl->sdl_data, sdl->sdl_nlen);
  338: 			nbuf[sdl->sdl_nlen] = '\0';
  339: 
  340: 			/* Add name to list */
  341: 			if ((new_list = REALLOC(mtype, list,
  342: 			    (num + 1) * sizeof(*list))) == NULL)
  343: 				goto fail;
  344: 			list = new_list;
  345: 			if ((list[num] = STRDUP(mtype, nbuf)) == NULL)
  346: 				goto fail;
  347: 			num++;
  348: 		}
  349: 	}
  350: 
  351: 	/* Done */
  352: 	FREE(TYPED_MEM_TEMP, buf);
  353: 	*listp = list;
  354: 	return (num);
  355: 
  356: fail:
  357: 	errno_save = errno;
  358: 	while (num > 0)
  359: 		FREE(mtype, list[--num]);
  360: 	FREE(mtype, list);
  361: 	FREE(TYPED_MEM_TEMP, buf);
  362: 	errno = errno_save;
  363: 	return (-1);
  364: }
  365: 
  366: /*
  367:  * Get the flags or type associated with an interface.
  368:  * Caller must free *bufp.
  369:  *
  370:  * Returns -1 and sets errno if there was a problem.
  371:  */
  372: static struct if_msghdr *
  373: if_find(const char *ifname, u_char **bufp, const char *mtype)
  374: {
  375: 	u_char *buf;
  376: 	u_char *ptr;
  377: 	size_t len;
  378: 
  379: 	/* Get raw data from kernel */
  380: 	if ((len = if_info(&buf, mtype)) == -1)
  381: 		return (NULL);
  382: 
  383: 	/* Scan for desired interface */
  384: 	for (ptr = buf;
  385: 	    ptr < buf + len;
  386: 	    ptr += ((struct if_msghdr *)(void *)ptr)->ifm_msglen) {
  387: 		struct if_msghdr *const ifm = (struct if_msghdr *)(void *)ptr;
  388: 		struct sockaddr_dl *sdl;
  389: 
  390: 		/* Sanity check version */
  391: 		if (ifm->ifm_version != RTM_VERSION) {
  392: 			FREE(mtype, buf);
  393: 			errno = EIO;
  394: 			return (NULL);
  395: 		}
  396: 
  397: 		/* Next interface or previous interface address? */
  398: 		if (ifm->ifm_type != RTM_IFINFO)
  399: 			continue;
  400: 
  401: 		/* Compare interface name */
  402: 		sdl = (struct sockaddr_dl *)(ifm + 1);
  403: 		if (strlen(ifname) != sdl->sdl_nlen ||
  404: 		    strncmp(ifname, sdl->sdl_data, sdl->sdl_nlen) != 0)
  405: 			continue;
  406: 
  407: 		/* Found it */
  408: 		*bufp = buf;
  409: 		return (ifm);
  410: 	}
  411: 
  412: 	/* Not found */
  413: 	FREE(mtype, buf);
  414: 	errno = ENOENT;
  415: 	return (NULL);
  416: }
  417: 
  418: /*
  419:  * Get the interface list. Caller must free *bufp.
  420:  */
  421: static int
  422: if_info(u_char **bufp, const char *mtype)
  423: {
  424: 	int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 };
  425: 	size_t length;
  426: 	u_char *buf;
  427: 
  428: 	if (sysctl(mib, 6, NULL, &length, NULL, 0) == -1)
  429: 		return (-1);
  430: 	length += 256;
  431: 	if ((buf = MALLOC(mtype, length)) == NULL)
  432: 		return (-1);
  433: 	if (sysctl(mib, 6, buf, &length, NULL, 0) == -1)
  434: 		return (-1);
  435: 	*bufp = buf;
  436: 	return (length);
  437: }
  438: 

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