]> Zhao Yanbai Git Server - minix.git/commitdiff
RS: add infrastructure for mapping socket drivers 17/3417/1
authorDavid van Moolenbroek <david@minix3.org>
Sun, 21 Feb 2016 18:43:17 +0000 (18:43 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 9 Mar 2017 23:39:49 +0000 (23:39 +0000)
This patch introduces the first piece of support for the concept of
"socket drivers": services that implement one or more socket protocol
families.  The latter are also known as "domains", as per the first
parameter of the socket(2) API.  More specifically, this patch adds
the basic infrastructure for specifying that a particular service is
the socket driver for a set of domains.

Unlike major number mappings for block and character drivers, socket
domain mappings are static.  For that reason, they are specified in
system.conf files, using the "domain" keyword.  Such a keyword is to
be followed by one or more protocol families, without their "PF_"
prefix.  For example, a service with the line "domain INET INET6;"
will be mapped as the socket driver responsible for the AF_INET and
AF_INET6 protocol families.

This patch implements only the infrastructure for creating such
mappings; the actual mapping will be implemented in VFS in a later
patch.  The infrastructure is implemented in service(8), RS, and VFS.

For now there is a hardcoded limit of eight domains per socket driver.
This may sound like a lot, but the upcoming new LWIP service will
already use four of those.  Also, it is allowed for a service to be
both a block/character driver and a socket driver at the same time,
which is a requirement for the new LWIP service.

Change-Id: I93352d488fc6c481e7079248082895d388c39f2d

minix/commands/minix-service/parse.c
minix/commands/minix-service/parse.h
minix/include/minix/config.h
minix/include/minix/ipc.h
minix/include/minix/rs.h
minix/include/minix/syslib.h
minix/lib/libsys/mapdriver.c
minix/servers/rs/manager.c
minix/servers/rs/proto.h
minix/servers/rs/request.c
minix/servers/vfs/dmap.c

index 3dcdc24a4f02a05d46cd55457a7f705580a3e752..ed49920cb197bb0fe55b64d0d216eabb0cb8d6b9 100644 (file)
@@ -26,6 +26,7 @@
 #include <minix/priv.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
 #include <configfile.h>
 
 #include <machine/archtypes.h>
@@ -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;
+               }
        }
 }
 
index 02fc0350f15ebd058f8039ebc48bff602d7bf0e7..b9e0e436b62da7a159720f9a477682196ee8b734 100644 (file)
@@ -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) */
index ac1f947812260ea85476cce7b0f2333a7bd0f91e..e8c944b6bace8087d34174b2eb6b6b07c2bd00de 100644 (file)
@@ -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.
  */
index fcedf4b3e124fc9f1aa2915ad62d71670ba469d2..13075e10a895b6cd4e856e12fd4a9d445ce80625 100644 (file)
@@ -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);
 
index 89005e6e6e910417935a4bb4330efd3ec6514aad..f2e6db6377ddf7a455dd50db4e2a90711e93cbe1 100644 (file)
@@ -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 */
index 1b5ebf11afc72be116015243d1e4feacdcc4cea9..a6a80a6c681c225734efefae82285561f1bbbc84 100644 (file)
@@ -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);
index f72e511a49c55aedbc06c631b9c300668009b340..7e616bb0cbb394c3dcc582b1eb87d8504ceb52f0 100644 (file)
@@ -4,14 +4,21 @@
 #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);
 }
index 85b81582c7eff7a7175e4735d150baf10b1b79be..d8602c090778e47a3c09ba7c37d02839b084c463 100644 (file)
@@ -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                              *
  *===========================================================================*/
index 11069cf9343414a6dcfddf9537807d69d2316266..ceafe4edf387271284b521adf65a19aa1a4f4477 100644 (file)
@@ -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);
index e022bcde0c3c4f7f1fbf8594498c72d963f8f418..abe371d5ddf0a7c81d8d199644cab4a9416de6d2 100644 (file)
@@ -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);
index 67d03ca4476c6a48f993b2a57aa5fab3c904acdf..bec47a5f0440da9cdfc74ca9ed257adfa6d8f234 100644 (file)
@@ -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;
 }
 
 /*===========================================================================*