home
/*
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation.
Based on David A. Hinds "mii-tools" code.
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <errno.h>
//Necessary data, from mii.h
#include <linux/sockios.h>
#ifndef SIOCGMIIPHY
#define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read any PHY register */
#endif
#include <linux/types.h>
/* This data structure is used for all the MII ioctl's */
struct mii_data {
__u16 phy_id;
__u16 reg_num;
__u16 val_in;
__u16 val_out;
};
#define MII_BMSR 0x01
#define MII_BMSR_LINK_VALID 0x0004
#define MII_BMCR 0x00
static struct ifreq ifr;
//set to 1 if you want more verbose
int verbose =1;
/*
* This func ups the iface. using the socket ioctl iface.
*/
void int_up (int skfd, char* ifname)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (skfd && ioctl(skfd, SIOCGIFFLAGS, &ifr) >= 0) {
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
ioctl(skfd, SIOCSIFFLAGS, &ifr);
}
}
void int_down (int skfd, char* ifname)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (skfd && ioctl(skfd, SIOCGIFFLAGS, &ifr) >= 0) {
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ifr.ifr_flags &= ~IFF_UP;
ioctl(skfd, SIOCSIFFLAGS, &ifr);
}
}
/****************************************************************/
static int mdio_read(int skfd, int location)
{
struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
mii->reg_num = location;
if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0) {
fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
strerror(errno));
return -1;
}
return mii->val_out;
}
int islinkup(int sock)
{
int mii_val[32], i, bmsr;
mdio_read(sock, MII_BMSR);
for (i = 0; i < ((verbose > 1) ? 32 : 8); i++)
mii_val[i] = mdio_read(sock, i);
if (mii_val[MII_BMCR] == 0xffff) {
fprintf(stderr, " No MII transceiver present!.\n");
return -1;
}
bmsr = mii_val[MII_BMSR];
return (bmsr & MII_BMSR_LINK_VALID) ? 1 : 0;
}
/*
* For this works on, the driver should implement the MII interface.
* Drivers knows who don't implement : pcnet32 :^P
* Tested on a sky2 / e100
*/
static int do_one_xcvr(char *ifname)
{
int skfd;
if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
perror("socket");
fprintf(stderr, " The int does not exist!.\n");
return 1;
}
int_up(skfd, ifname);
sleep (5);
/* Get the vitals from the interface. */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCGMIIPHY, &ifr) < 0) {
if ((errno != ENODEV))
fprintf(stderr, "SIOCGMIIPHY on '%s' failed: %s\n",
ifname, strerror(errno));
return 1;
}
if (islinkup(skfd))
{
printf ("La interfaz está levantada!\n");
}else printf ("La interafaz esta caída\n");
int_down(skfd, ifname);
return 0;
}
/*For testing pourposes.*/
int main (int argc, char * argv [])
{
if (argc != 2)
{
printf ("Introduce el nombre de la interfaz!!\n");
return 1;
}
int ret =do_one_xcvr(argv[1]);
if (ret != 0)
printf ("Error on definition...!!!!\n");
}