Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

eth-bsd.c

Go to the documentation of this file.
00001 /*
00002  * eth-bsd.c
00003  *
00004  * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
00005  *
00006  * $Id: eth-bsd.c,v 1.10 2005/01/25 21:30:39 dugsong Exp $
00007  */
00008 
00009 #include "config.h"
00010 
00011 #include <sys/param.h>
00012 #include <sys/types.h>
00013 #include <sys/ioctl.h>
00014 #include <sys/socket.h>
00015 #include <sys/time.h>
00016 #if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_ROUTE_RT_MSGHDR)
00017 #include <sys/sysctl.h>
00018 #include <net/route.h>
00019 #include <net/if_dl.h>
00020 #endif
00021 #include <net/bpf.h>
00022 #include <net/if.h>
00023 
00024 #include <assert.h>
00025 #include <errno.h>
00026 #include <fcntl.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 
00032 #include "dnet.h"
00033 
00034 struct eth_handle {
00035         int     fd;
00036         char    device[16];
00037 };
00038 
00039 eth_t *
00040 eth_open(const char *device)
00041 {
00042         struct ifreq ifr;
00043         char file[32];
00044         eth_t *e;
00045         int i;
00046 
00047         if ((e = calloc(1, sizeof(*e))) != NULL) {
00048                 for (i = 0; i < 32; i++) {
00049                         snprintf(file, sizeof(file), "/dev/bpf%d", i);
00050                         e->fd = open(file, O_WRONLY);
00051                         if (e->fd != -1 || errno != EBUSY)
00052                                 break;
00053                 }
00054                 if (e->fd < 0)
00055                         return (eth_close(e));
00056                 
00057                 memset(&ifr, 0, sizeof(ifr));
00058                 strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
00059                 
00060                 if (ioctl(e->fd, BIOCSETIF, (char *)&ifr) < 0)
00061                         return (eth_close(e));
00062 #ifdef BIOCSHDRCMPLT
00063                 i = 1;
00064                 if (ioctl(e->fd, BIOCSHDRCMPLT, &i) < 0)
00065                         return (eth_close(e));
00066 #endif
00067                 strlcpy(e->device, device, sizeof(e->device));
00068         }
00069         return (e);
00070 }
00071 
00072 ssize_t
00073 eth_send(eth_t *e, const void *buf, size_t len)
00074 {
00075         return (write(e->fd, buf, len));
00076 }
00077 
00078 eth_t *
00079 eth_close(eth_t *e)
00080 {
00081         if (e != NULL) {
00082                 if (e->fd >= 0)
00083                         close(e->fd);
00084                 free(e);
00085         }
00086         return (NULL);
00087 }
00088 
00089 #if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_ROUTE_RT_MSGHDR)
00090 int
00091 eth_get(eth_t *e, eth_addr_t *ea)
00092 {
00093         struct if_msghdr *ifm;
00094         struct sockaddr_dl *sdl;
00095         struct addr ha;
00096         u_char *p, *buf;
00097         size_t len;
00098         int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
00099 
00100         if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
00101                 return (-1);
00102         
00103         if ((buf = malloc(len)) == NULL)
00104                 return (-1);
00105         
00106         if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
00107                 free(buf);
00108                 return (-1);
00109         }
00110         for (p = buf; p < buf + len; p += ifm->ifm_msglen) {
00111                 ifm = (struct if_msghdr *)p;
00112                 sdl = (struct sockaddr_dl *)(ifm + 1);
00113                 
00114                 if (ifm->ifm_type != RTM_IFINFO ||
00115                     (ifm->ifm_addrs & RTA_IFP) == 0)
00116                         continue;
00117                 
00118                 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
00119                     memcmp(sdl->sdl_data, e->device, sdl->sdl_nlen) != 0)
00120                         continue;
00121                 
00122                 if (addr_ston((struct sockaddr *)sdl, &ha) == 0)
00123                         break;
00124         }
00125         free(buf);
00126         
00127         if (p >= buf + len) {
00128                 errno = ESRCH;
00129                 return (-1);
00130         }
00131         memcpy(ea, &ha.addr_eth, sizeof(*ea));
00132         
00133         return (0);
00134 }
00135 #else
00136 int
00137 eth_get(eth_t *e, eth_addr_t *ea)
00138 {
00139         errno = ENOSYS;
00140         return (-1);
00141 }
00142 #endif
00143 
00144 #if defined(SIOCSIFLLADDR)
00145 int
00146 eth_set(eth_t *e, const eth_addr_t *ea)
00147 {
00148         struct ifreq ifr;
00149         struct addr ha;
00150 
00151         ha.addr_type = ADDR_TYPE_ETH;
00152         ha.addr_bits = ETH_ADDR_BITS;
00153         memcpy(&ha.addr_eth, ea, ETH_ADDR_LEN);
00154         
00155         memset(&ifr, 0, sizeof(ifr));
00156         strlcpy(ifr.ifr_name, e->device, sizeof(ifr.ifr_name));
00157         addr_ntos(&ha, &ifr.ifr_addr);
00158         
00159         return (ioctl(e->fd, SIOCSIFLLADDR, &ifr));
00160 }
00161 #else
00162 int
00163 eth_set(eth_t *e, const eth_addr_t *ea)
00164 {
00165         errno = ENOSYS;
00166         return (-1);
00167 }
00168 #endif

Generated on Sun May 14 14:51:11 2006 by  doxygen 1.4.2