summaryrefslogtreecommitdiffstats
path: root/sbin/devd
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-07-10 03:37:15 +0000
committerimp <imp@FreeBSD.org>2005-07-10 03:37:15 +0000
commit68644ee7c20ae551f423483008f4f216eb31d6a5 (patch)
tree97e1fe11117d1944009f6913219eba532675f70d /sbin/devd
parent983982e20ac5470784e75ec16d45a9cbce75b15f (diff)
downloadFreeBSD-src-68644ee7c20ae551f423483008f4f216eb31d6a5.zip
FreeBSD-src-68644ee7c20ae551f423483008f4f216eb31d6a5.tar.gz
Add the ability to match the on a media type of the device in question.
Submitted by: sam Approved by: re (scottl)
Diffstat (limited to 'sbin/devd')
-rw-r--r--sbin/devd/devd.cc74
-rw-r--r--sbin/devd/devd.h1
-rw-r--r--sbin/devd/devd.hh16
-rw-r--r--sbin/devd/parse.y8
-rw-r--r--sbin/devd/token.l3
5 files changed, 101 insertions, 1 deletions
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc
index 228a0c4..9449322 100644
--- a/sbin/devd/devd.cc
+++ b/sbin/devd/devd.cc
@@ -190,6 +190,71 @@ match::do_match(config &c)
return retval;
}
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <net/if_media.h>
+
+media::media(config &c, const char *var, const char *type)
+ : _var(var), _type(-1)
+{
+ static struct ifmedia_description media_types[] = {
+ { IFM_ETHER, "Ethernet" },
+ { IFM_TOKEN, "Tokenring" },
+ { IFM_FDDI, "FDDI" },
+ { IFM_IEEE80211, "802.11" },
+ { IFM_ATM, "ATM" },
+ { IFM_CARP, "CARP" },
+ { -1, "unknown" },
+ { 0, NULL },
+ };
+ for (int i = 0; media_types[i].ifmt_string != NULL; i++)
+ if (strcasecmp(type, media_types[i].ifmt_string) == 0) {
+ _type = media_types[i].ifmt_word;
+ break;
+ }
+}
+
+media::~media()
+{
+}
+
+bool
+media::do_match(config &c)
+{
+ string value = c.get_variable("device-name");
+ struct ifmediareq ifmr;
+ bool retval;
+ int s;
+
+ if (Dflag)
+ fprintf(stderr, "Testing media type of %s against 0x%x\n",
+ value.c_str(), _type);
+
+ retval = false;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s >= 0) {
+ memset(&ifmr, 0, sizeof(ifmr));
+ strncpy(ifmr.ifm_name, value.c_str(), sizeof(ifmr.ifm_name));
+
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0 &&
+ ifmr.ifm_status & IFM_AVALID) {
+ if (Dflag)
+ fprintf(stderr, "%s has media type 0x%x\n",
+ value.c_str(), IFM_TYPE(ifmr.ifm_active));
+ retval = (IFM_TYPE(ifmr.ifm_active) == _type);
+ } else if (_type == -1) {
+ if (Dflag)
+ fprintf(stderr, "%s has unknown media type\n",
+ value.c_str());
+ retval = true;
+ }
+ close(s);
+ }
+
+ return retval;
+}
+
const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_";
const string var_list::nothing = "";
@@ -772,6 +837,15 @@ new_match(const char *var, const char *re)
return (e);
}
+eps *
+new_media(const char *var, const char *re)
+{
+ eps *e = new media(cfg, var, re);
+ free(const_cast<char *>(var));
+ free(const_cast<char *>(re));
+ return (e);
+}
+
void
set_pidfile(const char *name)
{
diff --git a/sbin/devd/devd.h b/sbin/devd/devd.h
index 8a032e4..a8d113b 100644
--- a/sbin/devd/devd.h
+++ b/sbin/devd/devd.h
@@ -43,6 +43,7 @@ void add_nomatch(int, struct event_proc *);
void add_notify(int, struct event_proc *);
struct event_proc *add_to_event_proc(struct event_proc *, struct eps *);
struct eps *new_match(const char *, const char *);
+struct eps *new_media(const char *, const char *);
struct eps *new_action(const char *);
void set_pidfile(const char *);
void set_variable(const char *, const char *);
diff --git a/sbin/devd/devd.hh b/sbin/devd/devd.hh
index 4730267..55af222 100644
--- a/sbin/devd/devd.hh
+++ b/sbin/devd/devd.hh
@@ -96,6 +96,22 @@ private:
};
/**
+ * media is the subclass used to match an individual variable. Its
+ * actions are nops.
+ */
+class media : public eps
+{
+public:
+ media(config &, const char *var, const char *type);
+ virtual ~media();
+ virtual bool do_match(config &);
+ virtual bool do_action(config &) { return true; }
+private:
+ std::string _var;
+ int _type;
+};
+
+/**
* action is used to fork a process. It matches everything.
*/
class action : public eps
diff --git a/sbin/devd/parse.y b/sbin/devd/parse.y
index 9269ef2..28b8a90 100644
--- a/sbin/devd/parse.y
+++ b/sbin/devd/parse.y
@@ -47,7 +47,7 @@
%token <str> STRING
%token <str> ID
%token OPTIONS SET DIRECTORY PID_FILE DEVICE_NAME ACTION MATCH
-%token ATTACH DETACH NOMATCH NOTIFY
+%token ATTACH DETACH NOMATCH NOTIFY MEDIA_TYPE CLASS SUBDEVICE
%type <eventproc> match_or_action_list
%type <eps> match_or_action match action
@@ -137,6 +137,12 @@ match
: MATCH STRING STRING SEMICOLON { $$ = new_match($2, $3); }
| DEVICE_NAME STRING SEMICOLON
{ $$ = new_match(strdup("device-name"), $2); }
+ | MEDIA_TYPE STRING SEMICOLON
+ { $$ = new_media(strdup("media-type"), $2); }
+ | CLASS STRING SEMICOLON
+ { $$ = new_match(strdup("class"), $2); }
+ | SUBDEVICE STRING SEMICOLON
+ { $$ = new_match(strdup("subdevice"), $2); }
;
action
diff --git a/sbin/devd/token.l b/sbin/devd/token.l
index 0aa8cb6..0fa78da 100644
--- a/sbin/devd/token.l
+++ b/sbin/devd/token.l
@@ -90,6 +90,9 @@ pid-file { return PID_FILE; }
attach { return ATTACH; }
detach { return DETACH; }
device-name { return DEVICE_NAME; }
+media-type { return MEDIA_TYPE; }
+class { return CLASS; }
+subdevice { return SUBDEVICE; }
action { return ACTION; }
match { return MATCH; }
nomatch { return NOMATCH; }
OpenPOWER on IntegriCloud