Annotation of embedaddon/coova-chilli/src/net.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * net library functions.
        !             3:  * Copyright (C) 2003, 2004, 2005, 2006 Mondru AB.
        !             4:  * Copyright (c) 2006-2008 David Bird <david@coova.com>
        !             5:  *
        !             6:  * The contents of this file may be used under the terms of the GNU
        !             7:  * General Public License Version 2, provided that the above copyright
        !             8:  * notice and this permission notice is included in all copies or
        !             9:  * substantial portions of the software.
        !            10:  *
        !            11:  */
        !            12: 
        !            13: #include "system.h"
        !            14: #include "syserr.h"
        !            15: #include "options.h"
        !            16: #include "net.h"
        !            17: 
        !            18: int dev_set_flags(char const *dev, int flags) {
        !            19:   struct ifreq ifr;
        !            20:   int fd;
        !            21:   
        !            22:   memset(&ifr, 0, sizeof(ifr));
        !            23:   ifr.ifr_flags = flags;
        !            24:   strncpy(ifr.ifr_name, dev, IFNAMSIZ);
        !            25:   ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
        !            26: 
        !            27:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        !            28:     log_err(errno,"socket() failed");
        !            29:     return -1;
        !            30:   }
        !            31: 
        !            32:   if (ioctl(fd, SIOCSIFFLAGS, &ifr)) {
        !            33:     log_err(errno,"ioctl(SIOCSIFFLAGS) failed");
        !            34:     close(fd);
        !            35:     return -1;
        !            36:   }
        !            37: 
        !            38:   close(fd);
        !            39: 
        !            40:   return 0;
        !            41: }
        !            42: 
        !            43: int dev_get_flags(char const *dev, int *flags) {
        !            44:   struct ifreq ifr;
        !            45:   int fd;
        !            46:   
        !            47:   memset(&ifr, 0, sizeof(ifr));
        !            48:   strncpy(ifr.ifr_name, dev, IFNAMSIZ);
        !            49:   ifr.ifr_name[IFNAMSIZ-1] = 0; 
        !            50: 
        !            51:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        !            52:     log_err(errno, "socket() failed");
        !            53:     return -1;
        !            54:   }
        !            55: 
        !            56:   if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
        !            57:     log_err(errno, "ioctl(SIOCSIFFLAGS) failed");
        !            58:     close(fd);
        !            59:     return -1;
        !            60:   }
        !            61: 
        !            62:   close(fd);
        !            63: 
        !            64:   *flags = ifr.ifr_flags;
        !            65: 
        !            66:   return 0;
        !            67: }
        !            68: 
        !            69: int dev_set_address(char const *devname, struct in_addr *address, 
        !            70:                    struct in_addr *dstaddr, struct in_addr *netmask) {
        !            71:   struct ifreq ifr;
        !            72:   int fd;
        !            73: 
        !            74:   memset (&ifr, 0, sizeof (ifr));
        !            75:   ifr.ifr_addr.sa_family = AF_INET;
        !            76:   ifr.ifr_dstaddr.sa_family = AF_INET;
        !            77: 
        !            78: #if defined(__linux__)
        !            79:   ifr.ifr_netmask.sa_family = AF_INET;
        !            80: 
        !            81: #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
        !            82:   ((struct sockaddr_in *) &ifr.ifr_addr)->sin_len = sizeof (struct sockaddr_in);
        !            83:   ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_len = sizeof (struct sockaddr_in);
        !            84: #endif
        !            85: 
        !            86:   strncpy(ifr.ifr_name, devname, IFNAMSIZ);
        !            87:   ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
        !            88: 
        !            89:   /* Create a channel to the NET kernel. */
        !            90:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        !            91:     log_err(errno, "socket() failed");
        !            92:     return -1;
        !            93:   }
        !            94: 
        !            95:   if (address) { /* Set the interface address */
        !            96:     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = address->s_addr;
        !            97:     if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
        !            98:       if (errno != EEXIST) {
        !            99:        log_err(errno, "ioctl(SIOCSIFADDR) failed");
        !           100:       }
        !           101:       else {
        !           102:        log_warn(errno, "ioctl(SIOCSIFADDR): Address already exists");
        !           103:       }
        !           104:       close(fd);
        !           105:       return -1;
        !           106:     }
        !           107:   }
        !           108: 
        !           109:   if (dstaddr) { /* Set the destination address */
        !           110:     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = dstaddr->s_addr;
        !           111:     if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
        !           112:       log_err(errno, "ioctl(SIOCSIFDSTADDR) failed");
        !           113:       close(fd);
        !           114:       return -1; 
        !           115:     }
        !           116:   }
        !           117: 
        !           118:   if (netmask) { /* Set the netmask */
        !           119: #if defined(__linux__)
        !           120:     ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr =  netmask->s_addr;
        !           121: 
        !           122: #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
        !           123:     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr =  netmask->s_addr;
        !           124: 
        !           125: #elif defined(__sun__)
        !           126:     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr =  netmask->s_addr;
        !           127: #else
        !           128: #error  "Unknown platform!" 
        !           129: #endif
        !           130: 
        !           131:     if (ioctl(fd, SIOCSIFNETMASK, (void *) &ifr) < 0) {
        !           132:       log_err(errno, "ioctl(SIOCSIFNETMASK) failed");
        !           133:       close(fd);
        !           134:       return -1;
        !           135:     }
        !           136:   }
        !           137:   
        !           138:   close(fd);
        !           139:   
        !           140:   return dev_set_flags(devname, IFF_UP | IFF_RUNNING); 
        !           141: }
        !           142: 
        !           143: int net_init(net_interface *netif, char *ifname, uint16_t protocol, int promisc, uint8_t *mac) {
        !           144:   memset(netif, 0, sizeof(net_interface));
        !           145:   strncpy(netif->devname, ifname, IFNAMSIZ);
        !           146:   netif->devname[IFNAMSIZ] = 0;
        !           147:   netif->protocol = protocol;
        !           148: 
        !           149:   if (promisc) netif->flags |= NET_PROMISC;
        !           150:   
        !           151:   if (mac) {
        !           152:     netif->flags |= NET_USEMAC;
        !           153:     memcpy(netif->hwaddr, mac, PKT_ETH_ALEN);
        !           154:   }
        !           155:   
        !           156:   return net_open(netif);
        !           157: }
        !           158: 
        !           159: int net_open(net_interface *netif) {
        !           160:   net_close(netif);
        !           161:   net_gflags(netif);
        !           162: 
        !           163:   if (!(netif->devflags & IFF_UP) || !(netif->devflags & IFF_RUNNING)) {
        !           164:     struct in_addr noaddr;
        !           165:     net_sflags(netif, netif->devflags | IFF_NOARP);
        !           166:     memset(&noaddr, 0, sizeof(noaddr));
        !           167:     dev_set_address(netif->devname, &noaddr, NULL, NULL);
        !           168:   }
        !           169: 
        !           170:   return net_open_eth(netif);
        !           171: }
        !           172: 
        !           173: int net_reopen(net_interface *netif) {
        !           174:   net_close(netif);
        !           175:   return net_open(netif);
        !           176: }
        !           177: 
        !           178: int net_set_address(net_interface *netif, struct in_addr *address, 
        !           179:                    struct in_addr *dstaddr, struct in_addr *netmask) {
        !           180:   netif->address.s_addr = address->s_addr;
        !           181:   netif->gateway.s_addr = dstaddr->s_addr;
        !           182:   netif->netmask.s_addr = netmask->s_addr;
        !           183: 
        !           184:   return dev_set_address(netif->devname, address, dstaddr, netmask);
        !           185: }
        !           186: 
        !           187: ssize_t net_read(net_interface *netif, void *d, size_t dlen) {
        !           188:   ssize_t len;
        !           189:   
        !           190:   if ((len = read(netif->fd, d, dlen)) < 0) {
        !           191: #ifdef ENETDOWN
        !           192:     if (errno == ENETDOWN) {
        !           193:       net_reopen(netif);
        !           194:     }
        !           195: #endif
        !           196:     log_err(errno, "read(fd=%d, len=%d) == %d", netif->fd, dlen, len);
        !           197:     return -1;
        !           198:   }
        !           199: 
        !           200:   return len;
        !           201: }
        !           202: 
        !           203: ssize_t net_write(net_interface *netif, void *d, size_t dlen) {
        !           204:   ssize_t len;
        !           205:   
        !           206:   if ((len = write(netif->fd, d, dlen)) < 0) {
        !           207: #ifdef ENETDOWN
        !           208:     if (errno == ENETDOWN) {
        !           209:       net_reopen(netif);
        !           210:     }
        !           211: #endif
        !           212:     log_err(errno, "write(fd=%d, len=%d) failed", netif->fd, dlen);
        !           213:     return -1;
        !           214:   }
        !           215: 
        !           216:   return len;
        !           217: }
        !           218: 
        !           219: int net_route(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask, int delete) {
        !           220: 
        !           221:   /* TODO: solaris!  */
        !           222: 
        !           223: #if defined(__linux__)
        !           224:   struct rtentry r;
        !           225:   int fd;
        !           226: 
        !           227:   memset (&r, 0, sizeof (r));
        !           228:   r.rt_flags = RTF_UP | RTF_GATEWAY; /* RTF_HOST not set */
        !           229: 
        !           230:   /* Create a channel to the NET kernel. */
        !           231:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        !           232:     log_err(errno, "socket() failed");
        !           233:     return -1;
        !           234:   }
        !           235: 
        !           236:   r.rt_dst.sa_family     = AF_INET;
        !           237:   r.rt_gateway.sa_family = AF_INET;
        !           238:   r.rt_genmask.sa_family = AF_INET;
        !           239:   ((struct sockaddr_in *) &r.rt_dst)->sin_addr.s_addr = dst->s_addr;
        !           240:   ((struct sockaddr_in *) &r.rt_gateway)->sin_addr.s_addr = gateway->s_addr;
        !           241:   ((struct sockaddr_in *) &r.rt_genmask)->sin_addr.s_addr = mask->s_addr;
        !           242:   
        !           243:   if (delete) {
        !           244:     if (ioctl(fd, SIOCDELRT, (void *) &r) < 0) {
        !           245:       log_err(errno,"ioctl(SIOCDELRT) failed");
        !           246:       close(fd);
        !           247:       return -1;
        !           248:     }
        !           249:   }
        !           250:   else {
        !           251:     if (ioctl(fd, SIOCADDRT, (void *) &r) < 0) {
        !           252:       log_err(errno, "ioctl(SIOCADDRT) failed");
        !           253:       close(fd);
        !           254:       return -1;
        !           255:     }
        !           256:   }
        !           257:   close(fd);
        !           258:   return 0;
        !           259:   
        !           260: #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
        !           261: 
        !           262:   struct {
        !           263:     struct rt_msghdr rt;
        !           264:     struct sockaddr_in dst;
        !           265:     struct sockaddr_in gate;
        !           266:     struct sockaddr_in mask;
        !           267:   } req;
        !           268:   
        !           269:   int fd;
        !           270:   struct rt_msghdr *rtm;
        !           271:   
        !           272:   if ((fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
        !           273:     log_err(errno, "socket() failed");
        !           274:     return -1;
        !           275:   }
        !           276:   
        !           277:   memset(&req, 0, sizeof(req));
        !           278:   
        !           279:   rtm  = &req.rt;
        !           280:   
        !           281:   rtm->rtm_msglen = sizeof(req);
        !           282:   rtm->rtm_version = RTM_VERSION;
        !           283:   if (delete) {
        !           284:     rtm->rtm_type = RTM_DELETE;
        !           285:   }
        !           286:   else {
        !           287:     rtm->rtm_type = RTM_ADD;
        !           288:   }
        !           289:   rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;  /* TODO */
        !           290:   rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
        !           291:   rtm->rtm_pid = getpid();      
        !           292:   rtm->rtm_seq = 0044;                                 /* TODO */
        !           293:   
        !           294:   req.dst.sin_family       = AF_INET;
        !           295:   req.dst.sin_len          = sizeof(req.dst);
        !           296:   req.mask.sin_family      = AF_INET;
        !           297:   req.mask.sin_len         = sizeof(req.mask);
        !           298:   req.gate.sin_family      = AF_INET;
        !           299:   req.gate.sin_len         = sizeof(req.gate);
        !           300:   
        !           301:   req.dst.sin_addr.s_addr  = dst->s_addr;
        !           302:   req.mask.sin_addr.s_addr = mask->s_addr;
        !           303:   req.gate.sin_addr.s_addr = gateway->s_addr;
        !           304:   
        !           305:   if (write(fd, rtm, rtm->rtm_msglen) < 0) {
        !           306:     log_err(errno, "write() failed");
        !           307:     close(fd);
        !           308:     return -1;
        !           309:   }
        !           310:   close(fd);
        !           311:   return 0;
        !           312:   
        !           313: #elif defined(__sun__)
        !           314:   log_err(errno, "Could not set up routing on Solaris. Please add route manually.");
        !           315:   return 0;
        !           316: #else
        !           317: #error  "Unknown platform!"
        !           318: #endif
        !           319: }
        !           320: 
        !           321: #if defined(__linux__)
        !           322: 
        !           323: /**
        !           324:  * Opens an Ethernet interface. As an option the interface can be set in
        !           325:  * promisc mode. If not null macaddr and ifindex are filled with the
        !           326:  * interface mac address and index
        !           327:  **/
        !           328: int net_open_eth(net_interface *netif) {
        !           329:   struct ifreq ifr;
        !           330:   struct packet_mreq mr;
        !           331:   struct sockaddr_ll sa;
        !           332:   int option = 1;
        !           333: 
        !           334:   memset(&ifr, 0, sizeof(ifr));
        !           335: 
        !           336:   /* Create socket */
        !           337:   if ((netif->fd = socket(PF_PACKET, SOCK_RAW, htons(netif->protocol))) < 0) {
        !           338:     if (errno == EPERM) {
        !           339:       log_err(errno, "Cannot create raw socket. Must be root.");
        !           340:     }
        !           341: 
        !           342:     log_err(errno, "socket(domain=%d, type=%lx, protocol=%d) failed",
        !           343:            PF_PACKET, SOCK_RAW, netif->protocol);
        !           344: 
        !           345:     return -1;
        !           346:   }
        !           347: 
        !           348:   /* Enable reception and transmission of broadcast frames */
        !           349:   if (setsockopt(netif->fd, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)) < 0) {
        !           350:     log_err(errno, "setsockopt(s=%d, level=%d, optname=%d, optlen=%d) failed",
        !           351:            netif->fd, SOL_SOCKET, SO_BROADCAST, sizeof(option));
        !           352:     return -1;
        !           353:   }
        !           354:   
        !           355:   /* Get the MAC address of our interface */
        !           356:   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
        !           357:   if (ioctl(netif->fd, SIOCGIFHWADDR, &ifr) < 0) {
        !           358:     log_err(errno, "ioctl(d=%d, request=%d) failed", netif->fd, SIOCGIFHWADDR);
        !           359:     return -1;
        !           360:   }
        !           361: 
        !           362:   if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
        !           363: 
        !           364:     netif->flags |= NET_ETHHDR;
        !           365: 
        !           366:     if ((netif->flags & NET_USEMAC) == 0)
        !           367:       memcpy(netif->hwaddr, ifr.ifr_hwaddr.sa_data, PKT_ETH_ALEN);
        !           368:   }
        !           369:   
        !           370:   if (netif->hwaddr[0] & 0x01) {
        !           371:     log_err(0, "Ethernet has broadcast or multicast address: %.16s", netif->devname);
        !           372:   }
        !           373: 
        !           374:   /* Get the current interface address, network, and any destination address */
        !           375: 
        !           376:   /* Verify that MTU = ETH_DATA_LEN */
        !           377:   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
        !           378:   if (ioctl(netif->fd, SIOCGIFMTU, &ifr) < 0) {
        !           379:     log_err(errno, "ioctl(d=%d, request=%d) failed", netif->fd, SIOCGIFMTU);
        !           380:     return -1;
        !           381:   }
        !           382:   if (ifr.ifr_mtu != ETH_DATA_LEN) {
        !           383:     log_err(0, "MTU does not match EHT_DATA_LEN: %d %d", ifr.ifr_mtu, ETH_DATA_LEN);
        !           384:     return -1;
        !           385:   }
        !           386: 
        !           387:   /* Get ifindex */
        !           388:   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
        !           389:   if (ioctl(netif->fd, SIOCGIFINDEX, &ifr) < 0) {
        !           390:     log_err(errno, "ioctl(SIOCFIGINDEX) failed");
        !           391:   }
        !           392:   netif->ifindex = ifr.ifr_ifindex;
        !           393:   
        !           394:   /* Set interface in promisc mode */
        !           395:   if (netif->flags & NET_PROMISC) {
        !           396:     memset(&mr,0,sizeof(mr));
        !           397:     mr.mr_ifindex = ifr.ifr_ifindex;
        !           398:     mr.mr_type =  PACKET_MR_PROMISC;
        !           399:     if (setsockopt(netif->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *)&mr, sizeof(mr)) < 0) {
        !           400:       log_err(errno, "setsockopt(s=%d, level=%d, optname=%d, optlen=%d) failed",
        !           401:              netif->fd, SOL_SOCKET, PACKET_ADD_MEMBERSHIP, sizeof(mr));
        !           402:       return -1;
        !           403:     }
        !           404:   }
        !           405: 
        !           406:   /* Bind to particular interface */
        !           407:   memset(&sa, 0, sizeof(sa));
        !           408:   sa.sll_family = AF_PACKET;
        !           409:   sa.sll_protocol = htons(netif->protocol);
        !           410:   sa.sll_ifindex = ifr.ifr_ifindex;
        !           411: 
        !           412:   if (bind(netif->fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
        !           413:     log_err(errno, "bind(sockfd=%d) failed", netif->fd);
        !           414:     return -1;
        !           415:   }
        !           416: 
        !           417:   return 0;
        !           418: }
        !           419: 
        !           420: #elif defined (__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
        !           421: 
        !           422: int net_getmac(const char *ifname, char *macaddr) {
        !           423: 
        !           424:   struct ifaddrs *ifap, *ifa;
        !           425:   struct sockaddr_dl *sdl;
        !           426: 
        !           427:   if (getifaddrs(&ifap)) {
        !           428:     log_err(errno, "getifaddrs() failed!");
        !           429:     return -1;
        !           430:   }
        !           431: 
        !           432:   ifa = ifap;
        !           433:   while (ifa) {
        !           434:     if ((strcmp(ifa->ifa_name, ifname) == 0) &&
        !           435:        (ifa->ifa_addr->sa_family == AF_LINK)) {
        !           436:       sdl = (struct sockaddr_dl *)ifa->ifa_addr;
        !           437:       switch(sdl->sdl_type) {
        !           438:       case IFT_ETHER:
        !           439: #ifdef IFT_IEEE80211
        !           440:       case IFT_IEEE80211:
        !           441: #endif
        !           442:        break;
        !           443:       default:
        !           444:        continue;
        !           445:       }
        !           446:       if (sdl->sdl_alen != PKT_ETH_ALEN) {
        !           447:        log_err(errno, "Wrong sdl_alen!");
        !           448:        freeifaddrs(ifap);
        !           449:        return -1;
        !           450:       }
        !           451:       memcpy(macaddr, LLADDR(sdl), PKT_ETH_ALEN);
        !           452:       freeifaddrs(ifap);
        !           453:       return 0;
        !           454:     }
        !           455:     ifa = ifa->ifa_next;
        !           456:   }  
        !           457:   freeifaddrs(ifap);
        !           458:   return -1;
        !           459: }
        !           460: 
        !           461: /**
        !           462:  * Opens an Ethernet interface. As an option the interface can be set in
        !           463:  * promisc mode. If not null macaddr and ifindex are filled with the
        !           464:  * interface mac address and index
        !           465:  **/
        !           466: 
        !           467: /* Relevant IOCTLs
        !           468: FIONREAD Get the number of bytes in input buffer
        !           469: SIOCGIFADDR Get interface address (IP)
        !           470: BIOCGBLEN, BIOCSBLEN Get and set required buffer length
        !           471: BIOCGDLT Type of underlying data interface
        !           472: BIOCPROMISC Set in promisc mode
        !           473: BIOCFLUSH Flushes the buffer of incoming packets
        !           474: BIOCGETIF, BIOCSETIF Set hardware interface. Uses ift_name
        !           475: BIOCSRTIMEOUT, BIOCGRTIMEOUT Set and get timeout for reads
        !           476: BIOCGSTATS Return stats for the interface
        !           477: BIOCIMMEDIATE Return immediately from reads as soon as packet arrives.
        !           478: BIOCSETF Set filter
        !           479: BIOCVERSION Return the version of BPF
        !           480: BIOCSHDRCMPLT BIOCGHDRCMPLT Set flag of wheather to fill in MAC address
        !           481: BIOCSSEESENT BIOCGSEESENT Return locally generated packets */
        !           482: 
        !           483: int net_open_eth(net_interface *netif) {
        !           484:   char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
        !           485:   int devnum;
        !           486:   struct ifreq ifr;
        !           487:   struct ifaliasreq areq;
        !           488:   int local_fd;
        !           489:   struct bpf_version bv;
        !           490: 
        !           491:   u_int32_t ipaddr;
        !           492:   struct sockaddr_dl hwaddr;
        !           493:   unsigned int value;
        !           494: 
        !           495:   /* Find suitable device */
        !           496:   for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */ 
        !           497:     snprintf(devname, sizeof(devname), "/dev/bpf%d", devnum);
        !           498:     devname[sizeof(devname)] = 0;
        !           499:     if ((netif->fd = open(devname, O_RDWR)) >= 0) break;
        !           500:     if (errno != EBUSY) break;
        !           501:   } 
        !           502:   if (netif->fd < 0) {
        !           503:     log_err(errno, "Can't find bpf device");
        !           504:     return -1;
        !           505:   }
        !           506: 
        !           507:   /* Set the interface */
        !           508:   memset(&ifr, 0, sizeof(ifr));
        !           509:   strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
        !           510:   if (ioctl(netif->fd, BIOCSETIF, &ifr) < 0) {
        !           511:     log_err(errno,"ioctl() failed");
        !           512:     return -1;
        !           513:   }
        !           514: 
        !           515:   /* Get and validate BPF version */
        !           516:   if (ioctl(netif->fd, BIOCVERSION, &bv) < 0) {
        !           517:     log_err(errno,"ioctl() failed!");
        !           518:     return -1;
        !           519:   }  
        !           520:   if (bv.bv_major != BPF_MAJOR_VERSION ||
        !           521:       bv.bv_minor < BPF_MINOR_VERSION) {
        !           522:     log_err(errno,"wrong BPF version!");
        !           523:     return -1;
        !           524:   }
        !           525: 
        !           526:   /* Get the MAC address of our interface */
        !           527:   if (net_getmac(netif->devname, netif->hwaddr)) {
        !           528:     log_err(0,"Did not find MAC address!");
        !           529:   }
        !           530:   else {
        !           531:     netif->flags |= NET_ETHHDR;
        !           532:   }
        !           533:   
        !           534:   if (netif->hwaddr[0] & 0x01) {
        !           535:     log_err(0, "Ethernet has broadcast or multicast address: %.16s", netif->devname);
        !           536:     return -1;
        !           537:   }
        !           538: 
        !           539:   /* Set interface in promisc mode */
        !           540:   if (netif->flags & NET_PROMISC) {
        !           541:     value = 1;
        !           542:     if (ioctl(netif->fd, BIOCPROMISC, NULL) < 0) {
        !           543:       log_err(errno,"ioctl() failed!");
        !           544:       return -1;
        !           545:     }  
        !           546:     value = 1;
        !           547:     if (ioctl(netif->fd, BIOCSHDRCMPLT, &value) < 0) {
        !           548:       log_err(errno,"ioctl() failed!");
        !           549:       return -1;
        !           550:     }  
        !           551:   }
        !           552:   else {
        !           553:     value = 0;
        !           554:     if (ioctl(netif->fd, BIOCSHDRCMPLT, &value) < 0) {
        !           555:       log_err(errno,"ioctl() failed!");
        !           556:       return -1;
        !           557:     }  
        !           558:   }
        !           559: 
        !           560:   /* Make sure reads return as soon as packet has been received */
        !           561:   value = 1;
        !           562:   if (ioctl(netif->fd, BIOCIMMEDIATE, &value) < 0) {
        !           563:     log_err(errno,"ioctl() failed!");
        !           564:     return -1;
        !           565:   }  
        !           566: 
        !           567:   return 0;
        !           568: }
        !           569: 
        !           570: #endif
        !           571: 

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