+ internal_cfg->create_uio_dev = 0;
+ internal_cfg->iova_mode = RTE_IOVA_DC;
+ internal_cfg->user_mbuf_pool_ops_name = NULL;
+ CPU_ZERO(&internal_cfg->ctrl_cpuset);
+ internal_cfg->init_complete = 0;
+ internal_cfg->max_simd_bitwidth.bitwidth = RTE_VECT_DEFAULT_SIMD_BITWIDTH;
+ internal_cfg->max_simd_bitwidth.forced = 0;
+}
+
+static int
+eal_plugin_add(const char *path)
+{
+ struct shared_driver *solib;
+
+ solib = malloc(sizeof(*solib));
+ if (solib == NULL) {
+ RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
+ return -1;
+ }
+ memset(solib, 0, sizeof(*solib));
+ strlcpy(solib->name, path, PATH_MAX);
+ TAILQ_INSERT_TAIL(&solib_list, solib, next);
+
+ return 0;
+}
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+int
+eal_plugins_init(void)
+{
+ return 0;
+}
+#else
+
+static int
+eal_plugindir_init(const char *path)
+{
+ DIR *d = NULL;
+ struct dirent *dent = NULL;
+ char sopath[PATH_MAX];
+
+ if (path == NULL || *path == '\0')
+ return 0;
+
+ d = opendir(path);
+ if (d == NULL) {
+ RTE_LOG(ERR, EAL, "failed to open directory %s: %s\n",
+ path, strerror(errno));
+ return -1;
+ }
+
+ while ((dent = readdir(d)) != NULL) {
+ struct stat sb;
+ int nlen = strnlen(dent->d_name, sizeof(dent->d_name));
+
+ /* check if name ends in .so or .so.ABI_VERSION */
+ if (strcmp(&dent->d_name[nlen - 3], ".so") != 0 &&
+ strcmp(&dent->d_name[nlen - 4 - strlen(ABI_VERSION)],
+ ".so."ABI_VERSION) != 0)
+ continue;
+
+ snprintf(sopath, sizeof(sopath), "%s/%s", path, dent->d_name);
+
+ /* if a regular file, add to list to load */
+ if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
+ continue;
+
+ if (eal_plugin_add(sopath) == -1)
+ break;
+ }
+
+ closedir(d);
+ /* XXX this ignores failures from readdir() itself */
+ return (dent == NULL) ? 0 : -1;
+}
+
+static int
+verify_perms(const char *dirpath)
+{
+ struct stat st;
+
+ /* if not root, check down one level first */
+ if (strcmp(dirpath, "/") != 0) {
+ static __thread char last_dir_checked[PATH_MAX];
+ char copy[PATH_MAX];
+ const char *dir;
+
+ strlcpy(copy, dirpath, PATH_MAX);
+ dir = dirname(copy);
+ if (strncmp(dir, last_dir_checked, PATH_MAX) != 0) {
+ if (verify_perms(dir) != 0)
+ return -1;
+ strlcpy(last_dir_checked, dir, PATH_MAX);
+ }
+ }
+
+ /* call stat to check for permissions and ensure not world writable */
+ if (stat(dirpath, &st) != 0) {
+ RTE_LOG(ERR, EAL, "Error with stat on %s, %s\n",
+ dirpath, strerror(errno));
+ return -1;
+ }
+ if (st.st_mode & S_IWOTH) {
+ RTE_LOG(ERR, EAL,
+ "Error, directory path %s is world-writable and insecure\n",
+ dirpath);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void *
+eal_dlopen(const char *pathname)
+{
+ void *retval = NULL;
+ char *realp = realpath(pathname, NULL);
+
+ if (realp == NULL && errno == ENOENT) {
+ /* not a full or relative path, try a load from system dirs */
+ retval = dlopen(pathname, RTLD_NOW);
+ if (retval == NULL)
+ RTE_LOG(ERR, EAL, "%s\n", dlerror());
+ return retval;
+ }
+ if (realp == NULL) {
+ RTE_LOG(ERR, EAL, "Error with realpath for %s, %s\n",
+ pathname, strerror(errno));
+ goto out;
+ }
+ if (strnlen(realp, PATH_MAX) == PATH_MAX) {
+ RTE_LOG(ERR, EAL, "Error, driver path greater than PATH_MAX\n");
+ goto out;
+ }
+
+ /* do permissions checks */
+ if (verify_perms(realp) != 0)
+ goto out;
+
+ retval = dlopen(realp, RTLD_NOW);
+ if (retval == NULL)
+ RTE_LOG(ERR, EAL, "%s\n", dlerror());
+out:
+ free(realp);
+ return retval;
+}
+
+static int
+is_shared_build(void)
+{
+#define EAL_SO "librte_eal.so"
+ char soname[32];
+ size_t len, minlen = strlen(EAL_SO);
+
+ len = strlcpy(soname, EAL_SO"."ABI_VERSION, sizeof(soname));
+ if (len > sizeof(soname)) {
+ RTE_LOG(ERR, EAL, "Shared lib name too long in shared build check\n");
+ len = sizeof(soname) - 1;
+ }
+
+ while (len >= minlen) {
+ /* check if we have this .so loaded, if so - shared build */
+ RTE_LOG(DEBUG, EAL, "Checking presence of .so '%s'\n", soname);
+ if (dlopen(soname, RTLD_LAZY | RTLD_NOLOAD) != NULL) {
+ RTE_LOG(INFO, EAL, "Detected shared linkage of DPDK\n");
+ return 1;
+ }
+
+ /* remove any version numbers off the end to retry */
+ while (len-- > 0)
+ if (soname[len] == '.') {
+ soname[len] = '\0';
+ break;
+ }
+ }
+
+ RTE_LOG(INFO, EAL, "Detected static linkage of DPDK\n");
+ return 0;