#include <minix/priv.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/socket.h>
#include <configfile.h>
#include <machine/archtypes.h>
}
}
+static const struct {
+ const char *name;
+ int domain;
+} domain_tab[] = {
+ /* PF_UNSPEC should not be in this table. */
+ { "LOCAL", PF_LOCAL },
+ { "INET", PF_INET },
+ { "IMPLINK", PF_IMPLINK },
+ { "PUP", PF_PUP },
+ { "CHAOS", PF_CHAOS },
+ { "NS", PF_NS },
+ { "ISO", PF_ISO },
+ { "ECMA", PF_ECMA },
+ { "DATAKIT", PF_DATAKIT },
+ { "CCITT", PF_CCITT },
+ { "SNA", PF_SNA },
+ { "DECnet", PF_DECnet },
+ { "DLI", PF_DLI },
+ { "LAT", PF_LAT },
+ { "HYLINK", PF_HYLINK },
+ { "APPLETALK", PF_APPLETALK },
+ { "OROUTE", PF_OROUTE },
+ { "LINK", PF_LINK },
+ { "XTP", PF_XTP },
+ { "COIP", PF_COIP },
+ { "CNT", PF_CNT },
+ { "RTIP", PF_RTIP },
+ { "IPX", PF_IPX },
+ { "INET6", PF_INET6 },
+ { "PIP", PF_PIP },
+ { "ISDN", PF_ISDN },
+ { "NATM", PF_NATM },
+ { "ARP", PF_ARP },
+ { "KEY", PF_KEY },
+ { "BLUETOOTH", PF_BLUETOOTH },
+ /* There is no PF_IEEE80211. */
+ { "MPLS", PF_MPLS },
+ { "ROUTE", PF_ROUTE },
+};
+
+/*
+ * Process a list of 'domain' protocol families for socket drivers.
+ */
+static void
+do_domain(config_t * cpe, struct rs_start * rs_start)
+{
+ unsigned int i;
+ int nr_domain, domain;
+
+ for (nr_domain = 0; cpe != NULL; cpe = cpe->next) {
+ if (cpe->flags & CFG_SUBLIST) {
+ fatal("do_domain: unexpected sublist at %s:%d",
+ cpe->file, cpe->line);
+ }
+ if (cpe->flags & CFG_STRING) {
+ fatal("do_domain: unexpected string at %s:%d",
+ cpe->file, cpe->line);
+ }
+ if (nr_domain >= __arraycount(rs_start->rss_domain)) {
+ fatal("do_domain: NR_DOMAIN is too small (%d needed)",
+ nr_domain + 1);
+ }
+
+ for (i = 0; i < __arraycount(domain_tab); i++)
+ if (!strcmp(domain_tab[i].name, (char *)cpe->word))
+ break;
+ if (i < __arraycount(domain_tab))
+ domain = domain_tab[i].domain;
+ else
+ domain = atoi((char *)cpe->word);
+
+ if (domain <= 0 || domain >= PF_MAX) {
+ fatal("do_domain: unknown domain %s at %s:%d",
+ (char *)cpe->word, cpe->file, cpe->line);
+ }
+
+ rs_start->rss_domain[nr_domain] = domain;
+ rs_start->rss_nr_domain = ++nr_domain;
+ }
+}
+
static void do_service(config_t *cpe, config_t *config, struct rs_config *rs_config)
{
struct rs_start *rs_start = &rs_config->rs_start;
do_control(cpe->next, rs_start);
continue;
}
+ if (strcmp(cpe->word, KW_DOMAIN) == 0)
+ {
+ do_domain(cpe->next, rs_start);
+ continue;
+ }
}
}
#define KW_TYPE "type" /* set service type */
#define KW_NET "net" /* ethernet driver type */
#define KW_DESCR "descr" /* human-readable string */
+#define KW_DOMAIN "domain" /* socket domain (protocol family) */
/* Max. number of IRQs that can be assigned to a process */
#define NR_IRQ 16
+/* Max. number of domains (protocol families) per socket driver */
+#define NR_DOMAIN 8
+
/* Scheduling priorities. Values must start at zero (highest
* priority) and increment.
*/
devmajor_t major;
size_t labellen;
vir_bytes label;
+ int ndomains;
+ int domains[NR_DOMAIN];
- uint8_t padding[44];
+ uint8_t padding[8];
} mess_lsys_vfs_mapdriver;
_ASSERT_MSG_SIZE(mess_lsys_vfs_mapdriver);
int devman_id;
char *rss_progname;
size_t rss_prognamelen;
+ int rss_nr_domain;
+ int rss_domain[NR_DOMAIN];
/*
* SMP specific data
*
endpoint_t new_endpoint; /* new instance endpoint number (for VM, when updating) */
devmajor_t dev_nr; /* major device number or NO_DEV */
+ int nr_domain; /* number of socket driver domains */
+ int domain[NR_DOMAIN]; /* set of socket driver domains */
char label[RS_MAX_LABEL_LEN]; /* label of this service */
char proc_name[RS_MAX_LABEL_LEN]; /* process name of this service */
pid_t srv_fork(uid_t reuid, gid_t regid);
int srv_kill(pid_t pid, int sig);
int getprocnr(pid_t pid, endpoint_t *proc_ep);
-int mapdriver(char *label, devmajor_t major);
+int mapdriver(const char *label, devmajor_t major, const int *domains,
+ int nr_domains);
pid_t getnpid(endpoint_t proc_ep);
uid_t getnuid(endpoint_t proc_ep);
gid_t getngid(endpoint_t proc_ep);
#include <unistd.h>
int
-mapdriver(char *label, devmajor_t major)
+mapdriver(const char * label, devmajor_t major, const int * domains,
+ int ndomains)
{
message m;
+ int i;
memset(&m, 0, sizeof(m));
m.m_lsys_vfs_mapdriver.label = (vir_bytes)label;
m.m_lsys_vfs_mapdriver.labellen = strlen(label) + 1;
m.m_lsys_vfs_mapdriver.major = major;
+ m.m_lsys_vfs_mapdriver.ndomains = ndomains;
+ if (ndomains > (int)__arraycount(m.m_lsys_vfs_mapdriver.domains))
+ ndomains = (int)__arraycount(m.m_lsys_vfs_mapdriver.domains);
+ for (i = 0; i < ndomains; i++)
+ m.m_lsys_vfs_mapdriver.domains[i] = domains[i];
return _taskcall(VFS_PROC_NR, VFS_MAPDRIVER, &m);
}
rpub->sys_flags &= ~(SF_CORE_SRV|SF_DET_RESTART);
rp->r_period = 0;
rpub->dev_nr = 0;
+ rpub->nr_domain = 0;
sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL);
}
}
/* If the service is a driver, map it. */
- if (rpub->dev_nr > 0) {
+ if (rpub->dev_nr > 0 || rpub->nr_domain > 0) {
/* The purpose of non-blocking forks is to avoid involving VFS in the
* forking process, because VFS may be blocked on a ipc_sendrec() to a MFS
* that is waiting for a endpoint update for a dead driver. We have just
*/
setuid(0);
- if ((r = mapdriver(rpub->label, rpub->dev_nr)) != OK) {
+ if ((r = mapdriver(rpub->label, rpub->dev_nr, rpub->domain,
+ rpub->nr_domain)) != OK) {
return kill_service(rp, "couldn't map driver", r);
}
}
{
struct rprocpub *def_rpub;
struct rprocpub *rpub;
+ int i;
def_rpub = def_rp->r_pub;
rpub = rp->r_pub;
- /* Device and PCI settings. These properties cannot change. */
+ /* Device, domain, and PCI settings. These properties cannot change. */
rpub->dev_nr = def_rpub->dev_nr;
+ rpub->nr_domain = def_rpub->nr_domain;
+ for (i = 0; i < def_rpub->nr_domain; i++)
+ rpub->domain[i] = def_rpub->domain[i];
rpub->pci_acl = def_rpub->pci_acl;
/* Immutable system and privilege flags. */
rp->r_uid= rs_start->rss_uid;
/* Initialize device driver settings. */
+ if (rs_start->rss_nr_domain < 0 || rs_start->rss_nr_domain > NR_DOMAIN) {
+ printf("RS: init_slot: too many domains\n");
+ return EINVAL;
+ }
+
rpub->dev_nr = rs_start->rss_major;
+ rpub->nr_domain = rs_start->rss_nr_domain;
+ for (i = 0; i < rs_start->rss_nr_domain; i++)
+ rpub->domain[i] = rs_start->rss_domain[i];
rpub->devman_id = rs_start->devman_id;
/* Initialize pci settings. */
return NULL;
}
+/*===========================================================================*
+ * lookup_slot_by_domain *
+ *===========================================================================*/
+struct rproc* lookup_slot_by_domain(int domain)
+{
+/* Lookup a service slot matching the given protocol family. */
+ int i, slot_nr;
+ struct rproc *rp;
+ struct rprocpub *rpub;
+
+ if (domain <= 0) {
+ return NULL;
+ }
+
+ for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
+ rp = &rproc[slot_nr];
+ rpub = rp->r_pub;
+ if (!(rp->r_flags & RS_IN_USE)) {
+ continue;
+ }
+ for (i = 0; i < rpub->nr_domain; i++)
+ if (rpub->domain[i] == domain)
+ return rp;
+ }
+
+ return NULL;
+}
+
/*===========================================================================*
* lookup_slot_by_flags *
*===========================================================================*/
struct rproc* lookup_slot_by_label(char *label);
struct rproc* lookup_slot_by_pid(pid_t pid);
struct rproc* lookup_slot_by_dev_nr(dev_t dev_nr);
+struct rproc* lookup_slot_by_domain(int domain);
struct rproc* lookup_slot_by_flags(int flags);
int alloc_slot(struct rproc **rpp);
void free_slot(struct rproc *rp);
/* A request was made to start a new system service. */
struct rproc *rp;
struct rprocpub *rpub;
- int r;
+ int i, r;
struct rs_start rs_start;
int noblock;
int init_flags = 0;
rpub->dev_nr);
return EBUSY;
}
+ for (i = 0; i < rpub->nr_domain; i++) {
+ if (lookup_slot_by_domain(rpub->domain[i]) != NULL) {
+ printf("RS: service with the same domain %d already exists\n",
+ rpub->domain[i]);
+ return EBUSY;
+ }
+ }
/* All information was gathered. Now try to start the system service. */
r = start_service(rp, init_flags);
* etc), and its label. This label is registered with DS, and allows us to
* retrieve the driver's endpoint.
*/
- int r, slot;
+ int r, slot, ndomains;
devmajor_t major;
endpoint_t endpoint;
vir_bytes label_vir;
label_vir = job_m_in.m_lsys_vfs_mapdriver.label;
label_len = job_m_in.m_lsys_vfs_mapdriver.labellen;
major = job_m_in.m_lsys_vfs_mapdriver.major;
+ ndomains = job_m_in.m_lsys_vfs_mapdriver.ndomains;
+ /* domains = job_m_in.m_lsys_vfs_mapdriver.domains; */
/* Get the label */
if (label_len > sizeof(label)) { /* Can we store this label? */
rfp->fp_flags |= FP_SRV_PROC;
/* Try to update device mapping. */
- return map_driver(label, major, endpoint);
+ if (major != NO_DEV) {
+ if ((r = map_driver(label, major, endpoint)) != OK)
+ return r;
+ }
+ if (ndomains != 0) {
+ r = EINVAL; /* TODO: add support for mapping socket drivers */
+ if (r != OK) {
+ if (major != NO_DEV)
+ map_driver(NULL, major, NONE); /* undo */
+ return r;
+ }
+ }
+ return OK;
}
/*===========================================================================*