Home | History | Annotate | Line # | Download | only in common
device.c revision 1.11
      1 /*	$NetBSD: device.c,v 1.11 2009/11/17 18:58:07 drochner Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1993-95 Mats O Jansson.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include <sys/cdefs.h>
     28 #ifndef lint
     29 __RCSID("$NetBSD: device.c,v 1.11 2009/11/17 18:58:07 drochner Exp $");
     30 #endif
     31 
     32 #include "os.h"
     33 #include "common.h"
     34 #include "device.h"
     35 #include "mopdef.h"
     36 #include "pf.h"
     37 #include "log.h"
     38 
     39 struct	if_info *iflist;		/* Interface List		*/
     40 
     41 void	deviceOpen(const char *, u_short, int);
     42 
     43 #ifdef	DEV_NEW_CONF
     44 /*
     45  * Return ethernet address for interface
     46  */
     47 
     48 void
     49 deviceEthAddr(const char *ifname, u_char *eaddr)
     50 {
     51 	struct sockaddr_dl *sdl;
     52 	struct ifaddrs *ifap, *ifa;
     53 
     54 	if (getifaddrs(&ifap) != 0)
     55 		mopLogErr("deviceEthAddr: getifaddrs");
     56 
     57 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
     58 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
     59 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
     60 		    sdl->sdl_alen != 6)
     61 			continue;
     62 		if (!strcmp(ifa->ifa_name, ifname)) {
     63 			memmove((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6);
     64 			freeifaddrs(ifap);
     65 			return;
     66 		}
     67 	}
     68 
     69 	freeifaddrs(ifap);
     70 	mopLogErrX("deviceEthAddr: Never saw interface `%s'!", ifname);
     71 }
     72 #endif	/* DEV_NEW_CONF */
     73 
     74 void
     75 deviceOpen(const char *ifname, u_short proto, int trans)
     76 {
     77 	struct if_info *p, tmp;
     78 
     79 	strlcpy(tmp.if_name, ifname, sizeof(tmp.if_name));
     80 	tmp.iopen   = pfInit;
     81 
     82 	switch (proto) {
     83 	case MOP_K_PROTO_RC:
     84 		tmp.read = mopReadRC;
     85 		tmp.fd   = mopOpenRC(&tmp, trans);
     86 		break;
     87 	case MOP_K_PROTO_DL:
     88 		tmp.read = mopReadDL;
     89 		tmp.fd   = mopOpenDL(&tmp, trans);
     90 		break;
     91 	default:
     92 		break;
     93 	}
     94 
     95 	if (tmp.fd != -1) {
     96 		p = (struct if_info *)malloc(sizeof(*p));
     97 		if (p == 0)
     98 			mopLogErr("deviceOpen: malloc");
     99 
    100 		p->next = iflist;
    101 		iflist = p;
    102 
    103 		strlcpy(p->if_name, tmp.if_name, sizeof(p->if_name));
    104 		p->iopen   = tmp.iopen;
    105 		p->write   = pfWrite;
    106 		p->read    = tmp.read;
    107 		memset((char *)p->eaddr, 0, sizeof(p->eaddr));
    108 		p->fd      = tmp.fd;
    109 
    110 #ifdef	DEV_NEW_CONF
    111 		deviceEthAddr(p->if_name,&p->eaddr[0]);
    112 #else
    113 		p->eaddr[0]= tmp.eaddr[0];
    114 		p->eaddr[1]= tmp.eaddr[1];
    115 		p->eaddr[2]= tmp.eaddr[2];
    116 		p->eaddr[3]= tmp.eaddr[3];
    117 		p->eaddr[4]= tmp.eaddr[4];
    118 		p->eaddr[5]= tmp.eaddr[5];
    119 #endif	/* DEV_NEW_CONF */
    120 
    121 	}
    122 }
    123 
    124 void
    125 deviceInitOne(const char *ifname)
    126 {
    127 	char	interface[IFNAME_SIZE];
    128 	struct if_info *p;
    129 	int	trans;
    130 #ifdef _AIX
    131 	char	dev[IFNAME_SIZE];
    132 	int	unit,j;
    133 
    134 	unit = 0;
    135 	for (j = 0; j < strlen(ifname); j++) {
    136 		if (isalpha(ifname[j])) {
    137 			dev[j] = ifname[j];
    138 		} else {
    139 			if (isdigit(ifname[j])) {
    140 				unit = unit*10 + ifname[j] - '0';
    141 				dev[j] = '\0';
    142 			}
    143 		}
    144 	}
    145 
    146 	if ((strlen(dev) == 2) &&
    147 	    (dev[0] == 'e') &&
    148 	    ((dev[1] == 'n') || (dev[1] == 't'))) {
    149 		snprintf(interface, sizeof(interface), "ent%d\0", unit);
    150 	} else {
    151 		snprintf(interface, sizeof(interface), "%s%d\0", dev, unit);
    152 	}
    153 #else
    154 	snprintf(interface, sizeof(interface), "%s", ifname);
    155 #endif /* _AIX */
    156 
    157 	/* Ok, init it just once */
    158 
    159 	p = iflist;
    160 	for (p = iflist; p; p = p->next)  {
    161 		if (strcmp(p->if_name,interface) == 0) {
    162 			return;
    163 		}
    164 	}
    165 
    166 	if (!mopInteractive)
    167 		syslog(LOG_INFO, "Initialized %s", interface);
    168 
    169 	/* Ok, get transport information */
    170 
    171 	trans = pfTrans(interface);
    172 
    173 #ifndef NORC
    174 	/* Start with MOP Remote Console */
    175 
    176 	switch (trans) {
    177 	case TRANS_ETHER:
    178 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
    179 		break;
    180 	case TRANS_8023:
    181 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
    182 		break;
    183 	case TRANS_ETHER+TRANS_8023:
    184 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
    185 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
    186 		break;
    187 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
    188 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023);
    189 		break;
    190 	}
    191 #endif
    192 
    193 #ifndef NODL
    194 	/* and next MOP Dump/Load */
    195 
    196 	switch (trans) {
    197 	case TRANS_ETHER:
    198 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
    199 		break;
    200 	case TRANS_8023:
    201 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
    202 		break;
    203 	case TRANS_ETHER+TRANS_8023:
    204 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
    205 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
    206 		break;
    207 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
    208 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023);
    209 		break;
    210 	}
    211 #endif
    212 
    213 }
    214 
    215 /*
    216  * Initialize all "candidate" interfaces that are in the system
    217  * configuration list.  A "candidate" is up, not loopback and not
    218  * point to point.
    219  */
    220 void
    221 deviceInitAll()
    222 {
    223 #ifdef	DEV_NEW_CONF
    224 	struct sockaddr_dl *sdl;
    225 	struct ifaddrs *ifap, *ifa;
    226 
    227 	if (getifaddrs(&ifap) != 0)
    228 		mopLogErr("deviceInitAll: socket");
    229 
    230 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    231 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
    232 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
    233 		    sdl->sdl_alen != 6)
    234 			continue;
    235 		if ((ifa->ifa_flags &
    236 		    (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
    237 			continue;
    238 		deviceInitOne(ifa->ifa_name);
    239 	}
    240 
    241 	freeifaddrs(ifap);
    242 #else
    243 	struct ifaddrs *ifap, *ifa;
    244 
    245 	if (getifaddrs(&ifap) != 0)
    246 		mopLogErr("deviceInitAll: old socket");
    247 
    248 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    249 		if (/*(ifa->ifa_flags & IFF_UP) == 0 ||*/
    250 		    ifa->ifa_flags & IFF_LOOPBACK ||
    251 		    ifa->ifa_flags & IFF_POINTOPOINT)
    252 			continue;
    253 		deviceInitOne(ifa->ifa_name);
    254 	}
    255 
    256 	freeifaddrs(ifap);
    257 #endif /* DEV_NEW_CONF */
    258 }
    259