- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "pcap_open_live: %s", pcap_strerror(errno));
- return (0);
- }
- memset(p, 0, sizeof(*p));
- p->fd = pfopen(device, O_RDONLY);
+ /*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ *
+ * XXX - we assume here that "pfopen()" does not, in fact, modify
+ * its argument, even though it takes a "char *" rather than a
+ * "const char *" as its first argument. That appears to be
+ * the case, at least on Digital UNIX 4.0.
+ *
+ * XXX - is there an error that means "no such device"? Is
+ * there one that means "that device doesn't support pf"?
+ */
+ p->fd = pfopen(p->opt.device, O_RDWR);
+ if (p->fd == -1 && errno == EACCES)
+ p->fd = pfopen(p->opt.device, O_RDONLY);