osl-linux.c

来自「Vista 核心Rally技术之-LLTD 实现源代码」· C语言 代码 · 共 1,126 行 · 第 1/3 页

C
1,126
字号
	    fclose(netdev);
	    return FALSE;
	}

	/* see if there's an optional ":DIGITS" virtual interface here */
	p = colon+1;
	while (isdigit(*p))
	    p++;
	if (*p == ':')
	    *p = '\0'; /* virtual interface name */
	else
	    *colon = '\0'; /* normal interface name */

	fn(name, state);
    }

    if (ferror(netdev))
    {
	warn("foreach_interface: error during reading of /proc/net/dev\n");
	fclose(netdev);
	return FALSE;
    }

#if CAN_FOPEN_IN_SELECT_LOOP
    fclose(netdev);
#endif
    return TRUE;
}


/* Recipe from section 1.7 of the Unix Programming FAQ */
/* http://www.erlenstar.demon.co.uk/unix/faq_toc.html */
void
osl_become_daemon(osl_t *osl)
{
    /* 1) fork */
    pid_t pid = fork();
    if (pid == -1)
	die("osl_become_daemon: fork to drop process group leadership failed: %s\n",
	    strerror(errno));
    if (pid != 0)
	exit(0); /* parent exits; child continues */

    /* we are now guaranteed not to be a process group leader */

    /* 2) setsid() */
    pid = setsid();
    if (pid == -1)
	die("osl_become_daemon: setsid failed?!: %s\n", strerror(errno));

    /* we are now the new group leader, and have successfully
     * jettisonned our controlling terminal - hooray! */
    
    /* 3) fork again */
    pid = fork();
    if (pid == -1)
	die("osl_become_daemon: fork to lose group leadership (again) failed: %s\n",
	    strerror(errno));
    if (pid != 0)
	exit(0); /* parent exits; child continues */

    /* we now have no controlling terminal, and are not a group leader
       (and thus have no way of acquiring a controlling terminal). */

    /* 4) chdir("/") */
    if (chdir("/") != 0)
	die("osl_become_daemon: chdir(\"/\") failed: %s\n", strerror(errno));
    /* this allows admins to umount filesystems etc since we're not
     * keeping them busy.*/

    /* 5) umask(0) */
    umask(0); /* if we create any files, we specify full mode bits */

    /* 6) close fds */

    /* 7) re-establish stdin/out/err to logfiles or /dev/console as needed */
}


/************************* E X T E R N A L S   f o r   T L V _ G E T _ F N s ***************************/
#define TLVDEF(_type, _name, _repeat, _number, _access, _inHello) \
extern int get_ ## _name (void *data);
#include "tlvdef.h"
#undef TLVDEF


/********************** T L V _ G E T _ F N s ******************************/

/* Return a 6-byte identifier which will be unique and consistent for
 * this host, across all of its interfaces.  Here we enumerate all the
 * interfaces that are up and have assigned Ethernet addresses, and
 * pick the lowest of them to represent this host.  */
int
get_hostid(void *data)
{
/*    TLVDEF( etheraddr_t, hostid,              ,   1,  Access_unset ) */

    etheraddr_t *hid = (etheraddr_t*) data;

    memcpy(hid,&Etheraddr_broadcast,sizeof(etheraddr_t));

    if (!foreach_interface(pick_lowest_address, hid))
    {
	if (TRACE(TRC_TLVINFO))
	    dbgprintf("get_hostid(): FAILED picking lowest address.\n");
	return TLV_GET_FAILED;
    }
    if (ETHERADDR_EQUALS(hid, &Etheraddr_broadcast))
    {
	if (TRACE(TRC_TLVINFO))
	    dbgprintf("get_hostid(): FAILED, because chosen hostid = broadcast address\n");
	return TLV_GET_FAILED;
    } else {
	if (TRACE(TRC_TLVINFO))
	    dbgprintf("get_hostid: hostid=" ETHERADDR_FMT "\n", ETHERADDR_PRINT(hid));
	return TLV_GET_SUCCEEDED;
    }
}


int
get_net_flags(void *data)
{
/*    TLVDEF( uint32_t,         net_flags,           ,   2,  Access_unset ) */

    uint32_t   nf;

#define fLP  0x08000000         // Looping back outbound packets, if set
#define fMW  0x10000000         // Has management web page accessible via HTTP, if set
#define fFD  0x20000000         // Full Duplex if set
#define fNX  0x40000000         // NAT private-side if set
#define fNP  0x80000000         // NAT public-side if set

    /* If your device has a management page at the url
            http://<device-ip-address>/
       then use the fMW flag, otherwise, remove it */
    nf = htonl(fFD | fMW);

    memcpy(data,&nf,4);

    return TLV_GET_SUCCEEDED;
}


int
get_physical_medium(void *data)
{
/*    TLVDEF( uint32_t,         physical_medium,     ,   3,  Access_unset ) */

    uint32_t   pm;

    pm = htonl(6);	// "ethernet"

    memcpy(data,&pm,4);

    return TLV_GET_SUCCEEDED;
}

#ifdef HAVE_WIRELESS

/* Return TRUE on successful query, setting "wireless_mode" to:
 *  0 = ad-hoc mode
 *  1 = infrastructure mode ie ESS (Extended Service Set) mode
 *  2 = auto/unknown (device may auto-switch between ad-hoc and infrastructure modes)
 */
int
get_wireless_mode(void *data)
{
/*    TLVDEF( uint32_t,         wireless_mode,       ,   4,  Access_unset ) */

    uint32_t* wl_mode = (uint32_t*) data;

    int rqfd;
    struct iwreq req;
    int ret;

    memset(&req, 0, sizeof(req));
    strncpy(req.ifr_ifrn.ifrn_name, g_osl->wireless_if, sizeof(req.ifr_ifrn.ifrn_name));
//*/printf("get_wireless_mode: requesting addr for interface \'%s\'\n",g_osl->wireless_if);
    rqfd = socket(AF_INET,SOCK_DGRAM,0);
    if (rqfd<0)
    {
        warn("get_wireless_mode: FAILED creating request socket for \'%s\' : %s\n",g_osl->wireless_if,strerror(errno));
        return FALSE;
    }
    ret = ioctl(rqfd, SIOCGIWMODE, &req);
    close(rqfd);
    if (ret != 0)
    {
	/* We don't whine about "Operation Not Supported" since that
	 * just means the interface does not have wireless extensions. */
	if (errno != EOPNOTSUPP  &&  errno != EFAULT)
	    warn("get_wireless_mode: get associated Access Point MAC failed: Error %d, %s\n",
		 errno,strerror(errno));
	return TLV_GET_FAILED;
    }

    switch (req.u.mode) {
    case IW_MODE_AUTO:
	*wl_mode = 2;
        break;

    case IW_MODE_ADHOC:
	*wl_mode = 0;
        break;

    case IW_MODE_INFRA:
	*wl_mode = 1;
        break;

    case IW_MODE_MASTER:
	*wl_mode = 1;
        break;

    case IW_MODE_REPEAT:
	*wl_mode = 1;
        break;

    case IW_MODE_SECOND:
	*wl_mode = 1;
        break;

    default:
	/* this is a wireless device that is probably acting
	 * as a listen-only monitor; we can't express its features like
	 * this, so we'll not return a wireless mode TLV. */
        IF_TRACED(TRC_TLVINFO)
            printf("get_wireless_mode(): mode (%d) unrecognizable - FAILING the get...\n", req.u.mode);
        END_TRACE
	return TLV_GET_FAILED;
    }
    IF_TRACED(TRC_TLVINFO)
        printf("get_wireless_mode(): wireless_mode=%d\n", *wl_mode);
    END_TRACE

    return TLV_GET_SUCCEEDED;
}


/* If the interface is 802.11 wireless in infrastructure mode, and it
 * has successfully associated to an AP (Access Point) then it will
 * have a BSSID (Basic Service Set Identifier), which is usually the
 * AP's MAC address. 
 * Of course, this code resides in an AP, so we just return the AP's
 * BSSID. */
int
get_bssid(void *data)
{
/*    TLVDEF( etheraddr_t, bssid,               ,   5,  Access_unset ) */

    etheraddr_t* bssid = (etheraddr_t*) data;

    struct iwreq req;
    int ret;

    memset(&req, 0, sizeof(req));
    strncpy(req.ifr_ifrn.ifrn_name, g_osl->wireless_if, sizeof(req.ifr_ifrn.ifrn_name));
    ret = ioctl(g_osl->sock, SIOCGIWAP, &req);
    if (ret != 0)
    {
	/* We don't whine about "Operation Not Supported" since that
	 * just means the interface does not have wireless extensions. */
	if (errno != EOPNOTSUPP)
	    warn("get_bssid: get associated Access Point MAC failed: %s\n",
		 strerror(errno));
        return TLV_GET_FAILED;
    }

    if (req.u.ap_addr.sa_family != ARPHRD_ETHER)
    {
	warn("get_bssid: expecting Ethernet address back, not sa_family=%d\n",
	     req.u.ap_addr.sa_family);
        return TLV_GET_FAILED;
    }

    memcpy(bssid, req.u.ap_addr.sa_data, sizeof(etheraddr_t));

    IF_TRACED(TRC_TLVINFO)
        printf("get_bssid(): bssid=" ETHERADDR_FMT "\n", ETHERADDR_PRINT(bssid));
    END_TRACE

    return TLV_GET_SUCCEEDED;
}


int
get_ssid(void *data)
{
/*    TLVDEF( ssid_t,           ssid,                ,   6,  Access_unset ) */

//    ssid_t* ssid = (ssid_t*) data;

    return TLV_GET_FAILED;
}

#endif /* HAVE_WIRELESS */


int
get_ipv4addr(void *data)
{
/*    TLVDEF( ipv4addr_t,       ipv4addr,            ,   7,  Access_unset ) */

    int          rqfd, ret;
    struct ifreq req;
    ipv4addr_t*  ipv4addr = (ipv4addr_t*) data;
    char         dflt_if[] = {"br0"};
    char        *interface = g_interface;

    if (interface == NULL) interface = dflt_if;
    memset(&req, 0, sizeof(req));
    strncpy(req.ifr_name, interface, sizeof(req.ifr_name));
    rqfd = socket(AF_INET,SOCK_DGRAM,0);
    if (rqfd<0)
    {
        warn("get_ipv4addr: FAILED creating request socket for \'%s\' : %s\n",interface,strerror(errno));
        return TLV_GET_FAILED;
    }
    ret = ioctl(rqfd, SIOCGIFADDR, &req);
    if (ret < 0)
    {
	warn("get_ipv4addr(%d,%s): FAILED : %s\n", rqfd, interface, strerror(errno));
	return TLV_GET_FAILED;
    }
    close(rqfd);
    IF_DEBUG
        /* Interestingly, the ioctl to get the ipv4 address returns that
           address offset by 2 bytes into the buf. Leaving this in case
           one of the ports results in a different offset... */
        unsigned char *d;
        d = (unsigned char*)req.ifr_addr.sa_data;
        /* Dump out the whole 14-byte buffer */
        printf("get_ipv4addr: sa_data = 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x\n",d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7],d[8],d[9],d[10],d[11],d[12],d[13]);
    END_DEBUG

    memcpy(ipv4addr,&req.ifr_addr.sa_data[2],sizeof(ipv4addr_t));
    IF_DEBUG
        printf("get_ipv4addr: returning %d.%d.%d.%d as ipv4addr\n", \
                *((uint8_t*)ipv4addr),*((uint8_t*)ipv4addr +1), \
                *((uint8_t*)ipv4addr +2),*((uint8_t*)ipv4addr +3));
    END_DEBUG

    return TLV_GET_SUCCEEDED;
}


int
get_ipv6addr(void *data)
{
/*    TLVDEF( ipv6addr_t,       ipv6addr,            ,   8,  Access_unset ) */

    ipv6addr_t* ipv6addr = (ipv6addr_t*) data;

    return TLV_GET_FAILED;
}


int
get_max_op_rate(void *data)
{
/*    TLVDEF( uint16_t,         max_op_rate,         ,   9,  Access_unset ) units of 0.5 Mbs */

    uint16_t	morate;

    morate = htons(108);	/* (OpenWRT, 802.11g) 54 Mbs / 0.5 Mbs = 108 */
    memcpy(data, &morate, 2);

    return TLV_GET_SUCCEEDED;
}


int
get_tsc_ticks_per_sec(void *data)
{
/*    TLVDEF( uint64_t,         tsc_ticks_per_sec,   , 0xA,  Access_unset ) */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?