diff options
author | imp <imp@FreeBSD.org> | 2005-07-10 03:37:15 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2005-07-10 03:37:15 +0000 |
commit | 68644ee7c20ae551f423483008f4f216eb31d6a5 (patch) | |
tree | 97e1fe11117d1944009f6913219eba532675f70d /sbin/devd | |
parent | 983982e20ac5470784e75ec16d45a9cbce75b15f (diff) | |
download | FreeBSD-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.cc | 74 | ||||
-rw-r--r-- | sbin/devd/devd.h | 1 | ||||
-rw-r--r-- | sbin/devd/devd.hh | 16 | ||||
-rw-r--r-- | sbin/devd/parse.y | 8 | ||||
-rw-r--r-- | sbin/devd/token.l | 3 |
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; } |