Logo Search packages:      
Sourcecode: laptop-net version File versions  Download package

linkup.c

/* -*-C-*-

$Id: linkup.c,v 1.8 2003/06/09 05:19:49 cph Exp $

Copyright 2000,2001,2002,2003 Massachusetts Institute of Technology

This file is part of laptop-net.

Laptop-net 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; either version 2 of the License, or (at your
option) any later version.

Laptop-net is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with laptop-net; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>

#include "probe.h"

static int read_if_flags (int, const char *, int *);
static int write_if_flags (int, const char *, int);

int
main (int argc, const char ** argv)
{
  const char * if_name;
  int option_verbose = 0;
  int fd;
  int if_flags;
  int up_p;
  int run_p;
  int conn_p;
  unsigned int retval;

  /* Choose the interface name. */
  if (argc == 2)
    if_name = (argv[1]);
  else if ((argc == 3) && ((strcmp ((argv[1]), "-v")) == 0))
    {
      if_name = (argv[2]);
      option_verbose = 1;
    }
  else
    {
      fprintf (stderr, "usage: %s [-v] <interface>\n", (argv[0]));
      return (1);
    }

  /* Open a basic socket. */
  fd = (socket (AF_INET, SOCK_DGRAM,0));
  if (fd < 0)
    {
      perror ("socket");
      return (1);
    }

  /* Get the vitals from the interface. */
  if ((read_if_flags (fd, if_name, (&if_flags))) < 0)
    {
      if (option_verbose)
      printf ("unknown\n");
      close (fd);
      return (1);
    }
  up_p = ((if_flags & IFF_UP) != 0);
  run_p = ((if_flags & IFF_RUNNING) != 0);

  /* As of 2.4.20, interfaces must be up in order to be interrogated.  */
  if (!up_p)
    write_if_flags (fd, if_name, (if_flags | IFF_UP));

  retval = (probe_link_ethtool (fd, if_name, (&conn_p)));
  if (retval == EOPNOTSUPP)
    retval = (probe_link_mii (fd, if_name, (&conn_p)));
  if (retval == EOPNOTSUPP)
    retval = (probe_link_old_mii (fd, if_name, (&conn_p)));

  if (!up_p)
    write_if_flags (fd, if_name, if_flags);

  close (fd);

#ifdef LINKUP_DEBUG
  fprintf (stderr, "linkup: %s 0x%x %d\n", if_name, if_flags, retval);
  fflush (stderr);
#endif

  if (retval > 0)
    {
      if (option_verbose)
      printf ("unknown\n");
      return (1);
    }

  if (option_verbose)
    printf
      ("%s,%s,%s\n",
       (up_p ? "up" : "down"),
       (run_p ? "running" : "stopped"),
       (conn_p ? "connected" : "disconnected"));
  return (conn_p ? 0 : 1);
}

static int
read_if_flags (int fd, const char * if_name, int * if_flags_r)
{
  struct ifreq ifr;
  strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
  if ((ioctl (fd, SIOCGIFFLAGS, (&ifr))) < 0)
    {
      fprintf (stderr, "SIOCGIFFLAGS on %s failed: %s\n", if_name,
             (strerror (errno)));
      return (-1);
    }
  (*if_flags_r) = (ifr . ifr_flags);
  return (0);
}

static int
write_if_flags (int fd, const char * if_name, int if_flags)
{
  struct ifreq ifr;
  strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
  (ifr . ifr_flags) = if_flags;
  if ((ioctl (fd, SIOCSIFFLAGS, (&ifr))) < 0)
    {
      fprintf (stderr, "SIOCSIFFLAGS on %s failed: %s\n", if_name,
             (strerror (errno)));
      return (-1);
    }
  return (0);
}

Generated by  Doxygen 1.6.0   Back to index