Bryan O'Sullivan avatar Bryan O'Sullivan committed 41c0769

Autoprobe for interfaces.
This is nceessary for interfaces that may have been compiled as kernel
modules and not yet loaded.

Comments (0)

Files changed (3)

     pat->pat = xmalloc(len + 1);
     memcpy(pat->pat, name, len + 1);
     pat->next = pats;
-    pats = pat->next;
+    pats = pat;
 
     return 0;
 }
 }
 
 
+static int
+has_meta(char *s)
+{
+    static const char meta[] = "[]*?";
+
+    for (char *x = s; *x != '\0'; x++) {
+	for (const char *m = meta; *m != '\0'; m++) {
+	    if (*x == *m) {
+		return x - s;
+	    }
+	}
+    }
+
+    return -1;
+}
+
+
+static int
+try_probe(char *iface)
+{
+    const char fmt[] = "exec /sbin/ip link set %s up >/dev/null 2>&1";
+    char cmd[sizeof(fmt) + strlen(iface)];
+    
+    sprintf(cmd, fmt, iface);
+    
+    int ret = system(cmd);
+
+    return ret == 0 ? 1 : 0;
+}
+
+
+void
+probe_interfaces(void)
+{
+    int nmatch = 0;
+    
+    for (struct if_pat *p = pats; p != NULL; p = p->next) {
+	int m;
+	
+	if ((m = has_meta(p->pat)) == -1) {
+	    nmatch += try_probe(p->pat);
+	}
+	else if (m == 0) {
+	    fprintf(stderr, "Warning: don't know how to probe for interfaces "
+		    "matching %s\n", p->pat);
+	    continue;
+	}
+	else {
+	    char *z = xmalloc(m + 4);
+	    
+	    strncpy(z, p->pat, m);
+	    
+	    for (int i = 0; i < 16; i++) {
+		sprintf(z + m, "%d", i);
+		if (fnmatch(p->pat, z, 0) == 0) {
+		    nmatch += try_probe(z);
+		}
+	    }
+
+	    free(z);
+	}
+    }
+
+    if (nmatch == 0) {
+	fprintf(stderr, "Warning: could not probe for any interfaces\n");
+    }
+}
+
+
 /*
  * Local variables:
  * c-file-style: "stroustrup"
 static void
 usage(int exitcode)
 {
-    fprintf(stderr, "Usage: netplug [-F] [-c config_file] [-i interface]\n");
+    fprintf(stderr, "Usage: netplug [-FP] [-c config_file] [-i interface]\n");
 
     fprintf(stderr, "\t-F\t\t"
 	    "run in foreground (don't become a daemon)\n");
+    fprintf(stderr, "\t-F\t\t"
+	    "do not autoprobe for interfaces (use with care)\n");
     fprintf(stderr, "\t-c config_file\t"
 	    "read interface patterns from this config file\n");
     fprintf(stderr, "\t-i interface\t"
     int c;
     int foreground = 0;
     int cfg_read = 0;
+    int probe = 1;
 
-    while ((c = getopt(argc, argv, "Fc:hi:")) != EOF) {
+    while ((c = getopt(argc, argv, "FPc:hi:")) != EOF) {
 	switch (c) {
 	case 'F':
 	    foreground = 1;
 	    break;
+	case 'P':
+	    probe = 0;
+	    break;
 	case 'c':
 	    read_config(optarg);
 	    cfg_read = 1;
 	read_config("/etc/netplug/netplug.conf");
     }
     
+    if (getuid() != 0) {
+	fprintf(stderr, "Warning: this command will not work properly unless "
+		"run by root\n");
+    }
+    
+    if (probe) {
+	probe_interfaces();
+    }
+    
     int fd = netlink_open();
 
     netlink_request_dump(fd);
 void read_config(char *filename);
 int save_pattern(char *pat);
 int if_match(char *name);
+void probe_interfaces(void);
 
 
 /* netlink interfacing */
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.