diff --git a/minix/commands/minix-service/parse.c b/minix/commands/minix-service/parse.c index 3dcdc24a4..ed49920cb 100644 --- a/minix/commands/minix-service/parse.c +++ b/minix/commands/minix-service/parse.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -942,6 +943,87 @@ static void do_control(config_t *cpe, struct rs_start *rs_start) } } +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; @@ -1058,6 +1140,11 @@ static void do_service(config_t *cpe, config_t *config, struct rs_config *rs_con do_control(cpe->next, rs_start); continue; } + if (strcmp(cpe->word, KW_DOMAIN) == 0) + { + do_domain(cpe->next, rs_start); + continue; + } } } diff --git a/minix/commands/minix-service/parse.h b/minix/commands/minix-service/parse.h index 02fc0350f..b9e0e436b 100644 --- a/minix/commands/minix-service/parse.h +++ b/minix/commands/minix-service/parse.h @@ -22,3 +22,4 @@ #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) */ diff --git a/minix/include/minix/config.h b/minix/include/minix/config.h index ac1f94781..e8c944b6b 100644 --- a/minix/include/minix/config.h +++ b/minix/include/minix/config.h @@ -57,6 +57,9 @@ /* 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. */ diff --git a/minix/include/minix/ipc.h b/minix/include/minix/ipc.h index fcedf4b3e..13075e10a 100644 --- a/minix/include/minix/ipc.h +++ b/minix/include/minix/ipc.h @@ -1426,8 +1426,10 @@ typedef struct { 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); diff --git a/minix/include/minix/rs.h b/minix/include/minix/rs.h index 89005e6e6..f2e6db637 100644 --- a/minix/include/minix/rs.h +++ b/minix/include/minix/rs.h @@ -139,6 +139,8 @@ struct rs_start int devman_id; char *rss_progname; size_t rss_prognamelen; + int rss_nr_domain; + int rss_domain[NR_DOMAIN]; /* * SMP specific data * @@ -168,6 +170,8 @@ struct rprocpub { 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 */ diff --git a/minix/include/minix/syslib.h b/minix/include/minix/syslib.h index 1b5ebf11a..a6a80a6c6 100644 --- a/minix/include/minix/syslib.h +++ b/minix/include/minix/syslib.h @@ -264,7 +264,8 @@ int tty_input_inject(int type, int code, int val); 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); diff --git a/minix/lib/libsys/mapdriver.c b/minix/lib/libsys/mapdriver.c index f72e511a4..7e616bb0c 100644 --- a/minix/lib/libsys/mapdriver.c +++ b/minix/lib/libsys/mapdriver.c @@ -4,14 +4,21 @@ #include 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); } diff --git a/minix/servers/rs/manager.c b/minix/servers/rs/manager.c index 85b81582c..d8602c090 100644 --- a/minix/servers/rs/manager.c +++ b/minix/servers/rs/manager.c @@ -521,6 +521,7 @@ struct rproc *rp; 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); } @@ -802,7 +803,7 @@ struct rproc *rp; /* pointer to service slot */ } /* 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 @@ -816,7 +817,8 @@ struct rproc *rp; /* pointer to service slot */ */ 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); } } @@ -1304,12 +1306,16 @@ struct rproc *rp; { 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. */ @@ -1724,7 +1730,15 @@ endpoint_t source; 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. */ @@ -1993,6 +2007,34 @@ struct rproc* lookup_slot_by_dev_nr(dev_t dev_nr) 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 * *===========================================================================*/ diff --git a/minix/servers/rs/proto.h b/minix/servers/rs/proto.h index 11069cf93..ceafe4edf 100644 --- a/minix/servers/rs/proto.h +++ b/minix/servers/rs/proto.h @@ -84,6 +84,7 @@ void swap_slot(struct rproc **src_rpp, struct rproc **dst_rpp); 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); diff --git a/minix/servers/rs/request.c b/minix/servers/rs/request.c index e022bcde0..abe371d5d 100644 --- a/minix/servers/rs/request.c +++ b/minix/servers/rs/request.c @@ -18,7 +18,7 @@ message *m_ptr; /* request message pointer */ /* 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; @@ -78,6 +78,13 @@ message *m_ptr; /* request message pointer */ 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); diff --git a/minix/servers/vfs/dmap.c b/minix/servers/vfs/dmap.c index 67d03ca44..bec47a5f0 100644 --- a/minix/servers/vfs/dmap.c +++ b/minix/servers/vfs/dmap.c @@ -110,7 +110,7 @@ int do_mapdriver(void) * 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; @@ -124,6 +124,8 @@ int do_mapdriver(void) 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? */ @@ -157,7 +159,19 @@ int do_mapdriver(void) 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; } /*===========================================================================*