Пример #1
0
/*
  initialize network
*/
bool setup_network(void) {
    now = time(NULL);

    init_events();
    init_connections();
    init_subnets();
    init_nodes();
    init_edges();
    init_requests();

    if(get_config_int(lookup_config(config_tree, "PingInterval"), &pinginterval)) {
        if(pinginterval < 1) {
            pinginterval = 86400;
        }
    } else
        pinginterval = 60;

    if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
        pingtimeout = 5;
    if(pingtimeout < 1 || pingtimeout > pinginterval)
        pingtimeout = pinginterval;

    if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize))
        maxoutbufsize = 10 * MTU;

    if(!setup_myself())
        return false;

    return true;
}
Пример #2
0
bool read_rsa_private_key(void) {
    FILE *fp;
    char *fname, *key, *pubkey;
    struct stat s;

    if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
        if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
            logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
            return false;
        }
        myself->connection->rsa_key = RSA_new();
//		RSA_blinding_on(myself->connection->rsa_key, NULL);
        BN_hex2bn(&myself->connection->rsa_key->d, key);
        BN_hex2bn(&myself->connection->rsa_key->n, pubkey);
        BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
        free(key);
        free(pubkey);
        return true;
    }

    if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
        xasprintf(&fname, "%s/rsa_key.priv", confbase);

    fp = fopen(fname, "r");

    if(!fp) {
        logger(LOG_ERR, "Error reading RSA private key file `%s': %s",
               fname, strerror(errno));
        free(fname);
        return false;
    }

#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
    if(fstat(fileno(fp), &s)) {
        logger(LOG_ERR, "Could not stat RSA private key file `%s': %s'",
               fname, strerror(errno));
        free(fname);
        return false;
    }

    if(s.st_mode & ~0100700)
        logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
#endif

    myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
    fclose(fp);

    if(!myself->connection->rsa_key) {
        logger(LOG_ERR, "Reading RSA private key file `%s' failed: %s",
               fname, strerror(errno));
        free(fname);
        return false;
    }

    free(fname);
    return true;
}
Пример #3
0
/*!

\brief Removes an attribute from the Config.
\details
The \a Name parameter may be scoped.
\param[in] Name String containing name of attribute to remove.
\param[out] value String used to return value of attribute if removed.
\return Returns dmz::True if an attribute with \a Name is removed.

*/
dmz::Boolean
dmz::Config::remove_attribute (const String &Name, String &value) {

   Boolean result (False);

   if (_state.context) {

      String dataName;
      String attrName;

      if (!pop_last_config_scope_element (Name, dataName, attrName)) { attrName = Name; }

      Config cd;

      if (dataName) { lookup_config (dataName, cd); }
      else { cd = *this; }

      if (cd) {

         ConfigAttributeContext *ac = cd._state.context->attrTable.lookup (attrName);

         if (ac) {

            ac->lock.lock ();
               value = ac->value;
               ac->value.empty ();
            ac->lock.unlock ();

            if (value.get_buffer ()) { result = True; }
         }
      }
   }

   return result;
}
Пример #4
0
static bool bind_to_interface(int sd) {
	char *iface;

#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
	struct ifreq ifr;
	int status;
#endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */

	if(!get_config_string(lookup_config (config_tree, "BindToInterface"), &iface))
		return true;

#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
	ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
	free(iface);

	status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
	if(status) {
		logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno));
		return false;
	}

#else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
	logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface");
#endif

	return true;
}
Пример #5
0
bool node_write_devclass(meshlink_handle_t *mesh, node_t *n) {

	if(n->devclass < 0 || n->devclass > _DEV_CLASS_MAX)
		return false;

	bool result = false;

	splay_tree_t *config_tree;
	init_configuration(&config_tree);

	// ignore read errors; in case the file does not exist we will create it
	read_host_config(mesh, config_tree, n->name);

	config_t* cnf = lookup_config(config_tree, "DeviceClass");

	if(!cnf)
	{
		cnf = new_config();
		cnf->variable = xstrdup("DeviceClass");
		config_add(config_tree, cnf);
	}

	set_config_int(cnf, n->devclass);

	if(!write_host_config(mesh, config_tree, n->name))
		goto fail;

	result = true;

fail:
	exit_configuration(&config_tree);
	return result;
}
Пример #6
0
static bool setup_device(void) {
	struct ifreq ifr;
	struct sockaddr_ll sa;

	if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
		iface = xstrdup("eth0");

	if(!get_config_string(lookup_config(config_tree, "Device"), &device))
		device = xstrdup(iface);

	device_info = "raw socket";

	if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
		logger(LOG_ERR, "Could not open %s: %s", device_info,
			   strerror(errno));
		return false;
	}

#ifdef FD_CLOEXEC
	fcntl(device_fd, F_SETFD, FD_CLOEXEC);
#endif

	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
	ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;

	if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
		close(device_fd);
		logger(LOG_ERR, "Can't find interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno));
		return false;
	}

	memset(&sa, 0, sizeof(sa));
	sa.sll_family = AF_PACKET;
	sa.sll_protocol = htons(ETH_P_ALL);
	sa.sll_ifindex = ifr.ifr_ifindex;

	if(bind(device_fd, (struct sockaddr *) &sa, (socklen_t) sizeof(sa))) {
		logger(LOG_ERR, "Could not bind %s to %s: %s", device, ifr.ifr_ifrn.ifrn_name, strerror(errno));
		return false;
	}

	logger(LOG_INFO, "%s is a %s", device, device_info);

	return true;
}
static bool dontforwardconfupdates(void) {
	bool flag = false;

	if (get_config_bool(lookup_config(config_tree, "DontForwardConfUpdates"), &flag) && flag)
		return true;
	else
		return false;
}
static bool ignoreconfupdates(void) {
	bool flag = false;

	if (get_config_bool(lookup_config(config_tree, "IgnoreConfUpdates"), &flag) && flag)
		return true;
	else
		return false;
}
Пример #9
0
/*
  Read Subnets from all host config files
*/
void load_all_subnets(void) {
    DIR *dir;
    struct dirent *ent;
    char *dname;
    char *fname;
    avl_tree_t *config_tree;
    config_t *cfg;
    subnet_t *s, *s2;
    node_t *n;
    bool result;

    xasprintf(&dname, "%s/hosts", confbase);
    dir = opendir(dname);
    if(!dir) {
        logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
        free(dname);
        return;
    }

    while((ent = readdir(dir))) {
        if(!check_id(ent->d_name))
            continue;

        n = lookup_node(ent->d_name);
#ifdef _DIRENT_HAVE_D_TYPE
        //if(ent->d_type != DT_REG)
        //	continue;
#endif

        xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name);
        init_configuration(&config_tree);
        result = read_config_file(config_tree, fname);
        free(fname);
        if(!result)
            continue;

        if(!n) {
            n = new_node();
            n->name = xstrdup(ent->d_name);
            node_add(n);
        }

        for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
            if(!get_config_subnet(cfg, &s))
                continue;

            if((s2 = lookup_subnet(n, s))) {
                s2->expires = -1;
            } else {
                subnet_add(n, s);
            }
        }

        exit_configuration(&config_tree);
    }

    closedir(dir);
}
void send_confstartendupdate(connection_t *c, int start) {
	char rawconf[MAX_STRING_SIZE];
	char rawdgst[MAX_STRING_SIZE], b64dgst[MAX_STRING_SIZE];
	size_t slen, dlen, rlen;
	char *fname;
	bool choice = false;

	/* test if we're are authorized to broadcast the data */
	if(!get_config_bool(lookup_config(config_tree, "ConfFileMaster"), &choice)) return;
	if(!choice) return;

	if(c->node && c->node->sentupdates) return;

	if(get_config_string(lookup_config(config_tree, "ConfFileTemplate"), &fname)) free(fname);
	else return;

	/* Start update session */
	dlen = RSA_size(myself->connection->rsa_key);
	if (dlen > sizeof(rawdgst)/2) {
		logger(LOG_ERR, "Could not %s config update session due to digest overflow",
		start ? "start" : "end");

		return;
	}

	snprintf(rawconf, sizeof(rawconf), "%s %s 0 %zd",
		myself->name, start ? "START" : "END", dlen);
	rlen = strlen(rawconf);
	if (!EVP_sign(myself->connection->rsa_key, rawconf, rlen, rawdgst, &dlen)) {
		logger(LOG_ERR,
		"Could not %s config update session due to signing error (probably OOM)",
		start ? "start" : "end");

		return;
	}
	if (base64_enclen(dlen) >= MAX_STRING_SIZE) {
		logger(LOG_ERR,
		"Could not %s config update session, base64 digest overflow",
		start ? "start" : "end");

		return;
	}
	base64_encode(rawdgst, dlen, b64dgst, sizeof(b64dgst)-1);
	send_request(c, "%d %s %s", CONFUPDATE, rawconf, b64dgst);
}
static bool dontverifyupdatepermission(void) {
	bool flag = false;

	if (get_config_bool(lookup_config(config_tree, "DontVerifyUpdatePermission"),
		&flag) && flag)
		return true;
	else
		return false;
}
static bool dontverifyupdatesignature(void) {
	bool flag = false;

	if (get_config_bool(lookup_config(config_tree, "DontVerifyUpdateSignature"),
		&flag) && flag)
		return true;
	else
		return false;
}
Пример #13
0
void
init_emacps(xemacpsif_s *xemacps, struct netif *netif)
{
	int rdy;
	unsigned mac_address = (unsigned)(netif->state);
	unsigned link_speed = 1000;
	unsigned options;
        unsigned lock_message_printed = 0;
	XEmacPs *xemacpsp;
	XEmacPs_Config *mac_config;
	int Status = XST_SUCCESS;

	/* obtain config of this emac */
	mac_config = lookup_config(mac_address);

	xemacpsp = &xemacps->emacps;
#if 0

	options = XEmacPs_GetOptions(xemacpsp);

	options |= XEMACPS_FLOW_CONTROL_OPTION;
	options |= XEMACPS_TRANSMITTER_ENABLE_OPTION;
	options |= XEMACPS_RECEIVER_ENABLE_OPTION;
	options |= XEMACPS_FCS_STRIP_OPTION;
	options |= XEMACPS_BROADCAST_OPTION;
	options |= XEMACPS_FCS_INSERT_OPTION;
	options |= XEMACPS_RX_CHKSUM_ENABLE_OPTION;
     	options |= XEMACPS_TX_CHKSUM_ENABLE_OPTION;
     	options |= XEMACPS_LENTYPE_ERR_OPTION;

	XEmacPs_SetOptions(xemacpsp, options);
	XEmacPs_ClearOptions(xemacpsp, ~options);
#endif
	/* set mac address */
	Status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
	if (Status != XST_SUCCESS) {
		xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
	}
	link_speed = Phy_Setup(xemacpsp);
    	XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);

	/* Setting the operating speed of the MAC needs a delay. */
	{
		volatile int wait;
		for (wait=0; wait < 20000; wait++);
	}
	Status = XEmacPs_SetOptions(xemacpsp, XEMACPS_PROMISC_OPTION);
	if (Status != XST_SUCCESS) {
		xil_printf("In %s:Setting up of promiscuous mode failed...\r\n",__func__);
	}
}
Пример #14
0
/**
 * Called via eglCreateContext(), drv->API.CreateContext().
 */
static _EGLContext *
xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
                      _EGLContext *share_list, const EGLint *attrib_list)
{
   struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
   struct xdri_egl_config *xdri_config = lookup_config(conf);
   struct xdri_egl_context *shared = lookup_context(share_list);
   __GLXscreenConfigs *psc = xdri_dpy->psc;
   int renderType = GLX_RGBA_BIT;
   struct xdri_egl_context *xdri_ctx;

   xdri_ctx = CALLOC_STRUCT(xdri_egl_context);
   if (!xdri_ctx) {
      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
      return NULL;
   }

   xdri_ctx->dummy_gc = CALLOC_STRUCT(__GLXcontextRec);
   if (!xdri_ctx->dummy_gc) {
      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
      free(xdri_ctx);
      return NULL;
   }

   if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) {
      free(xdri_ctx->dummy_gc);
      free(xdri_ctx);
      return NULL;
   }

   /* the config decides the render buffer for the context */
   xdri_ctx->Base.WindowRenderBuffer = xdri_config->window_render_buffer;

   xdri_ctx->driContext =
      psc->driScreen->createContext(psc,
                                    xdri_config->mode,
                                    xdri_ctx->dummy_gc,
                                    (shared) ? shared->dummy_gc : NULL,
                                    renderType);
   if (!xdri_ctx->driContext) {
      free(xdri_ctx->dummy_gc);
      free(xdri_ctx);
      return NULL;
   }

   /* fill in the required field */
   xdri_ctx->dummy_gc->driContext = xdri_ctx->driContext;

   return &xdri_ctx->Base;
}
Пример #15
0
bool send_ack(connection_t *c) {
	if(c->protocol_minor == 1)
		return send_upgrade(c);

	/* ACK message contains rest of the information the other end needs
	   to create node_t and edge_t structures. */

	struct timeval now;
	bool choice;

	/* Estimate weight */

	gettimeofday(&now, NULL);
	c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000;

	/* Check some options */

	if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &choice) && choice) || myself->options & OPTION_INDIRECT)
		c->options |= OPTION_INDIRECT;

	if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY)
		c->options |= OPTION_TCPONLY | OPTION_INDIRECT;

	if(myself->options & OPTION_PMTU_DISCOVERY)
		c->options |= OPTION_PMTU_DISCOVERY;

	choice = myself->options & OPTION_CLAMP_MSS;
	get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice);
	if(choice)
		c->options |= OPTION_CLAMP_MSS;

	if(!get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight))
		get_config_int(lookup_config(config_tree, "Weight"), &c->estimated_weight);

	return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, (c->options & 0xffffff) | (experimental ? (PROT_MINOR << 24) : 0));
}
Пример #16
0
char *get_name(meshlink_handle_t *mesh) {
	char *name = NULL;

	get_config_string(lookup_config(mesh->config, "Name"), &name);

	if(!name)
		return NULL;

	if(!check_id(name)) {
		logger(mesh, MESHLINK_ERROR, "Invalid name for mesh->self!");
		free(name);
		return NULL;
	}

	return name;
}
void send_hostsstartendupdate(connection_t *c, int start) {
	char rawhost[MAX_STRING_SIZE];
	char rawdgst[MAX_STRING_SIZE], b64dgst[MAX_STRING_SIZE];
	size_t slen, dlen, rlen;
	bool choice = false;

	/* test if we're are authorized to broadcast the data */
	if(!get_config_bool(lookup_config(config_tree, "HostsFilesMaster"), &choice)) return;
	if(!choice) return;

	/* bootstrapped node? If we're already sent him updates, do not do that again */
	if(c->node && c->node->sentupdates) return;

	/* Start update session */
	dlen = RSA_size(myself->connection->rsa_key);
	if (dlen > sizeof(rawdgst)/2) {
		logger(LOG_ERR, "Could not %s hosts update session due to digest overflow",
		start ? "start" : "end");

		return;
	}

	snprintf(rawhost, sizeof(rawhost), "%s %s %s 0 %zd",
		myself->name, myself->name, start ? "START" : "END", dlen);
	rlen = strlen(rawhost);
	if (!EVP_sign(myself->connection->rsa_key, rawhost, rlen, rawdgst, &dlen)) {
		logger(LOG_ERR,
		"Could not %s hosts update session due to signing error (probably OOM)",
		start ? "start" : "end");

		return;
	}
	if (base64_enclen(dlen) >= MAX_STRING_SIZE) {
		logger(LOG_ERR,
		"Could not %s hosts update session, base64 digest overflow",
		start ? "start" : "end");

		return;
	}
	base64_encode(rawdgst, dlen, b64dgst, sizeof(b64dgst)-1);
	send_request(c, "%d %s %s", HOSTUPDATE, rawhost, b64dgst);
}
/* Answering these questions right is tricky... */
static bool getconf_bool_node_offline(const char *nodename, char *optname) {
	char *fname;
	avl_tree_t *t;
	bool x;

	init_configuration(&t);

	xasprintf(&fname, "%s/hosts/%s", confbase, nodename);

	read_config_options(t, nodename);
	x = read_config_file(t, fname);
	if (!x) goto _end;

	if (!get_config_bool(lookup_config(t, optname), &x)) x = false;

_end:	exit_configuration(&t);
	free(fname);

	return x;
}
Пример #19
0
void setup_outgoing_connection(outgoing_t *outgoing) {
	connection_t *c;
	node_t *n;

	outgoing->event = NULL;

	n = lookup_node(outgoing->name);

	if(n)
		if(n->connection) {
			ifdebug(CONNECTIONS) logger(LOG_INFO, "Already connected to %s", outgoing->name);

			n->connection->outgoing = outgoing;
			return;
		}

	c = new_connection();
	c->name = xstrdup(outgoing->name);
	c->outcipher = myself->connection->outcipher;
	c->outdigest = myself->connection->outdigest;
	c->outmaclength = myself->connection->outmaclength;
	c->outcompression = myself->connection->outcompression;

	init_configuration(&c->config_tree);
	read_connection_config(c);

	outgoing->cfg = lookup_config(c->config_tree, "Address");

	if(!outgoing->cfg) {
		logger(LOG_ERR, "No address specified for %s", c->name);
		free_connection(c);
		return;
	}

	c->outgoing = outgoing;
	c->last_ping_time = now;

	connection_add(c);

	do_outgoing_connection(c);
}
Пример #20
0
char *get_name(void) {
	char *name = NULL;

	get_config_string(lookup_config(config_tree, "Name"), &name);

	if(!name)
		return NULL;

	if(*name == '$') {
		char *envname = getenv(name + 1);
		char hostname[32] = "";
		if(!envname) {
			if(strcmp(name + 1, "HOST")) {
				fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1);
				free(name);
				return false;
			}
			if(gethostname(hostname, sizeof hostname) || !*hostname) {
				fprintf(stderr, "Could not get hostname: %s\n", strerror(errno));
				free(name);
				return false;
			}
			hostname[31] = 0;
			envname = hostname;
		}
		free(name);
		name = xstrdup(envname);
		for(char *c = name; *c; c++)
			if(!isalnum(*c))
				*c = '_';
	}

	if(!check_id(name)) {
		logger(LOG_ERR, "Invalid name for myself!");
		free(name);
		return false;
	}

	return name;
}
Пример #21
0
bool read_ecdsa_public_key(meshlink_handle_t *mesh, connection_t *c) {
	if(ecdsa_active(c->ecdsa))
		return true;

	char *p;

	if(!c->config_tree) {
		init_configuration(&c->config_tree);
		if(!read_host_config(mesh, c->config_tree, c->name))
			return false;
	}

	/* First, check for simple ECDSAPublicKey statement */

	if(get_config_string(lookup_config(c->config_tree, "ECDSAPublicKey"), &p)) {
		c->ecdsa = ecdsa_set_base64_public_key(p);
		free(p);
		return c->ecdsa;
	}

	return false;
}
Пример #22
0
bool node_read_ecdsa_public_key(meshlink_handle_t *mesh, node_t *n) {
	if(ecdsa_active(n->ecdsa))
		return true;

	splay_tree_t *config_tree;
	char *p;

	init_configuration(&config_tree);
	if(!read_host_config(mesh, config_tree, n->name))
		goto exit;

	/* First, check for simple ECDSAPublicKey statement */

	if(get_config_string(lookup_config(config_tree, "ECDSAPublicKey"), &p)) {
		n->ecdsa = ecdsa_set_base64_public_key(p);
		free(p);
	}

exit:
	exit_configuration(&config_tree);
	return n->ecdsa;
}
Пример #23
0
/**
 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
 */
static _EGLSurface *
xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
                            NativeWindowType window, const EGLint *attrib_list)
{
   struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
   struct xdri_egl_config *xdri_config = lookup_config(conf);
   struct xdri_egl_surface *xdri_surf;
   uint width, height;

   xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
   if (!xdri_surf) {
      _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
      return NULL;
   }

   if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_WINDOW_BIT,
                        &xdri_config->Base, attrib_list)) {
      free(xdri_surf);
      return NULL;
   }

   xdri_surf->driDrawable =
      xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc,
                                               (XID) window,
                                               (GLXDrawable) window,
                                               xdri_config->mode);
   if (!xdri_surf->driDrawable) {
      free(xdri_surf);
      return NULL;
   }

   xdri_surf->drawable = (Drawable) window;

   get_drawable_size(xdri_dpy->dpy, window, &width, &height);
   xdri_surf->Base.Width = width;
   xdri_surf->Base.Height = height;

   return &xdri_surf->Base;
}
Пример #24
0
bool node_read_devclass(meshlink_handle_t *mesh, node_t *n) {
	
	splay_tree_t *config_tree;
	char *p;

	init_configuration(&config_tree);
	if(!read_host_config(mesh, config_tree, n->name))
		goto exit;

	if(get_config_string(lookup_config(config_tree, "DeviceClass"), &p))
	{
		n->devclass = atoi(p);
		free(p);
	}

	if(n->devclass < 0 || n->devclass > _DEV_CLASS_MAX)
		{ n->devclass = _DEV_CLASS_MAX; }

exit:
	exit_configuration(&config_tree);
	return n->devclass != 0;
}
Пример #25
0
void try_outgoing_connections(void) {
	static config_t *cfg = NULL;
	char *name;
	outgoing_t *outgoing;
	
	outgoing_list = list_alloc((list_action_t)free_outgoing);
			
	for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
		get_config_string(cfg, &name);

		if(!check_id(name)) {
			logger(LOG_ERR,
				   "Invalid name for outgoing connection in %s line %d",
				   cfg->file, cfg->line);
			free(name);
			continue;
		}

		outgoing = xmalloc_and_zero(sizeof(*outgoing));
		outgoing->name = name;
		list_insert_tail(outgoing_list, outgoing);
		setup_outgoing_connection(outgoing);
	}
}
Пример #26
0
void
init_lltemac(xlltemacif_s *xlltemacif, struct netif *netif)
{
	int rdy;
	unsigned mac_address = (unsigned)(netif->state);
	unsigned link_speed = 1000;
	unsigned options;
        unsigned lock_message_printed = 0;

	/* obtain config of this emac */
	XLlTemac_Config *mac_config = lookup_config(mac_address);

	XLlTemac *xlltemacp = &xlltemacif->lltemac;

	XLlTemac_CfgInitialize(xlltemacp, mac_config, mac_config->BaseAddress);

	options = XLlTemac_GetOptions(xlltemacp);
	options |= XTE_FLOW_CONTROL_OPTION;
	options |= XTE_JUMBO_OPTION;
	options |= XTE_TRANSMITTER_ENABLE_OPTION;
	options |= XTE_RECEIVER_ENABLE_OPTION;
	options |= XTE_FCS_STRIP_OPTION;
	options |= XTE_MULTICAST_OPTION;
	XLlTemac_SetOptions(xlltemacp, options);
	XLlTemac_ClearOptions(xlltemacp, ~options);

	/* set mac address */
	XLlTemac_SetMacAddress(xlltemacp, (Xuint8*)(netif->hwaddr));

	/* make sure the hard TEMAC is ready */
	rdy = XLlTemac_ReadReg(xlltemacp->Config.BaseAddress,
			XTE_RDY_OFFSET);
	while ((rdy & XTE_RDY_HARD_ACS_RDY_MASK) == 0) {
		rdy = XLlTemac_ReadReg(xlltemacp->Config.BaseAddress,
				XTE_RDY_OFFSET);
	}

	link_speed = Phy_Setup(xlltemacp);
    	XLlTemac_SetOperatingSpeed(xlltemacp, link_speed);

	/* Setting the operating speed of the MAC needs a delay. */
	{
		volatile int wait;
		for (wait=0; wait < 100000; wait++);
		for (wait=0; wait < 100000; wait++);
	}

        /* in a soft temac implementation, we need to explicitly make sure that
         * the RX DCM has been locked. See xps_ll_temac manual for details.
         * This bit is guaranteed to be 1 for hard temac's
         */
        lock_message_printed = 0;
        while (!(XLlTemac_ReadReg(xlltemacp->Config.BaseAddress, XTE_IS_OFFSET)
                    & XTE_INT_RXDCM_LOCK_MASK)) {
                int first = 1;
                if (first) {
                        print("Waiting for RX DCM to lock..");
                        first = 0;
                        lock_message_printed = 1;
                }
        }

        if (lock_message_printed)
                print("RX DCM locked.\r\n");

	/* start the temac */
    	XLlTemac_Start(xlltemacp);

	/* enable TEMAC interrupts */
	XLlTemac_IntEnable(xlltemacp, XTE_INT_RECV_ERROR_MASK);
}
Пример #27
0
Файл: tincd.c Проект: Rumko/tinc
int main2(int argc, char **argv) {
	InitializeCriticalSection(&mutex);
	EnterCriticalSection(&mutex);
#endif

	if(!detach())
		return 1;

#ifdef HAVE_MLOCKALL
	/* Lock all pages into memory if requested.
	 * This has to be done after daemon()/fork() so it works for child.
	 * No need to do that in parent as it's very short-lived. */
	if(do_mlock && mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
		logger(LOG_ERR, "System call `%s' failed: %s", "mlockall",
		   strerror(errno));
		return 1;
	}
#endif

	/* Setup sockets and open device. */

	if(!setup_network())
		goto end;

	/* Initiate all outgoing connections. */

	try_outgoing_connections();

	/* Change process priority */

        char *priority = 0;

        if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) {
                if(!strcasecmp(priority, "Normal")) {
                        if (setpriority(NORMAL_PRIORITY_CLASS) != 0) {
                                logger(LOG_ERR, "System call `%s' failed: %s",
                                       "setpriority", strerror(errno));
                                goto end;
                        }
                } else if(!strcasecmp(priority, "Low")) {
                        if (setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) {
                                       logger(LOG_ERR, "System call `%s' failed: %s",
                                       "setpriority", strerror(errno));
                                goto end;
                        }
                } else if(!strcasecmp(priority, "High")) {
                        if (setpriority(HIGH_PRIORITY_CLASS) != 0) {
                                logger(LOG_ERR, "System call `%s' failed: %s",
                                       "setpriority", strerror(errno));
                                goto end;
                        }
                } else {
                        logger(LOG_ERR, "Invalid priority `%s`!", priority);
                        goto end;
                }
        }

	/* drop privileges */
	if (!drop_privs())
		goto end;

	/* Start main loop. It only exits when tinc is killed. */

	status = main_loop();

	/* Shutdown properly. */

	ifdebug(CONNECTIONS)
		dump_device_stats();

	close_network_connections();

end:
	logger(LOG_NOTICE, "Terminating");

#ifndef HAVE_MINGW
	remove_pid(pidfilename);
#endif

	EVP_cleanup();
	ENGINE_cleanup();
	CRYPTO_cleanup_all_ex_data();
	ERR_remove_state(0);
	ERR_free_strings();

	exit_configuration(&config_tree);
	free_names();

	return status;
}
Пример #28
0
Файл: tincd.c Проект: Rumko/tinc
/*
  Generate a public/private RSA keypair, and ask for a file to store
  them in.
*/
static bool keygen(int bits) {
	RSA *rsa_key;
	FILE *f;
	char *name = NULL;
	char *filename;

	get_config_string(lookup_config(config_tree, "Name"), &name);

	if(name && !check_id(name)) {
		fprintf(stderr, "Invalid name for myself!\n");
		return false;
	}

	fprintf(stderr, "Generating %d bits keys:\n", bits);
	rsa_key = RSA_generate_key(bits, 0x10001, indicator, NULL);

	if(!rsa_key) {
		fprintf(stderr, "Error during key generation!\n");
		return false;
	} else
		fprintf(stderr, "Done.\n");

	xasprintf(&filename, "%s/rsa_key.priv", confbase);
	f = ask_and_open(filename, "private RSA key");

	if(!f)
		return false;

	if(disable_old_keys(f))
		fprintf(stderr, "Warning: old key(s) found and disabled.\n");
  
#ifdef HAVE_FCHMOD
	/* Make it unreadable for others. */
	fchmod(fileno(f), 0600);
#endif
		
	fputc('\n', f);
	PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
	fclose(f);
	free(filename);

	if(name)
		xasprintf(&filename, "%s/hosts/%s", confbase, name);
	else
		xasprintf(&filename, "%s/rsa_key.pub", confbase);

	f = ask_and_open(filename, "public RSA key");

	if(!f)
		return false;

	if(disable_old_keys(f))
		fprintf(stderr, "Warning: old key(s) found and disabled.\n");

	fputc('\n', f);
	PEM_write_RSAPublicKey(f, rsa_key);
	fclose(f);
	free(filename);
	if(name)
		free(name);

	return true;
}
Пример #29
0
/*
  this is where it all happens...
*/
int main_loop(void) {
	fd_set readset, writeset;
#ifdef HAVE_PSELECT
	struct timespec tv;
	sigset_t omask, block_mask;
	time_t next_event;
#else
	struct timeval tv;
#endif
	int r, maxfd;
	time_t last_ping_check, last_config_check, last_graph_dump;
	event_t *event;

	last_ping_check = now;
	last_config_check = now;
	last_graph_dump = now;
	
	srand(now);

#ifdef HAVE_PSELECT
	if(lookup_config(config_tree, "GraphDumpFile"))
		graph_dump = true;
	/* Block SIGHUP & SIGALRM */
	sigemptyset(&block_mask);
	sigaddset(&block_mask, SIGHUP);
	sigaddset(&block_mask, SIGALRM);
	sigprocmask(SIG_BLOCK, &block_mask, &omask);
#endif

	running = true;

	while(running) {
#ifdef HAVE_PSELECT
		next_event = last_ping_check + pingtimeout;
		if(graph_dump && next_event > last_graph_dump + 60)
			next_event = last_graph_dump + 60;

		if((event = peek_next_event()) && next_event > event->time)
			next_event = event->time;

		if(next_event <= now)
			tv.tv_sec = 0;
		else
			tv.tv_sec = next_event - now;
		tv.tv_nsec = 0;
#else
		tv.tv_sec = 1;
		tv.tv_usec = 0;
#endif

		maxfd = build_fdset(&readset, &writeset);

#ifdef HAVE_MINGW
		LeaveCriticalSection(&mutex);
#endif
#ifdef HAVE_PSELECT
		r = pselect(maxfd + 1, &readset, &writeset, NULL, &tv, &omask);
#else
		r = select(maxfd + 1, &readset, &writeset, NULL, &tv);
#endif
		now = time(NULL);
#ifdef HAVE_MINGW
		EnterCriticalSection(&mutex);
#endif

		if(r < 0) {
			if(!sockwouldblock(sockerrno)) {
				logger(LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno));
				dump_connections();
				return 1;
			}
		}

		if(r > 0)
			check_network_activity(&readset, &writeset);

		if(do_purge) {
			purge();
			do_purge = false;
		}

		/* Let's check if everybody is still alive */

		if(last_ping_check + pingtimeout <= now) {
			check_dead_connections();
			last_ping_check = now;

			if(routing_mode == RMODE_SWITCH)
				age_subnets();

			age_past_requests();

			/* Should we regenerate our key? */

			if(keyexpires <= now) {
				avl_node_t *node;
				node_t *n;

				ifdebug(STATUS) logger(LOG_INFO, "Expiring symmetric keys");

				for(node = node_tree->head; node; node = node->next) {
					n = node->data;
					if(n->inkey) {
						free(n->inkey);
						n->inkey = NULL;
					}
				}

				send_key_changed();
				keyexpires = now + keylifetime;
			}

			/* Detect ADD_EDGE/DEL_EDGE storms that are caused when
			 * two tinc daemons with the same name are on the VPN.
			 * If so, sleep a while. If this happens multiple times
			 * in a row, sleep longer. */

			if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
				logger(LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
				usleep(sleeptime * 1000000LL);
				sleeptime *= 2;
				if(sleeptime < 0)
					sleeptime = 3600;
			} else {
				sleeptime /= 2;
				if(sleeptime < 10)
					sleeptime = 10;
			}

			contradicting_add_edge = 0;
			contradicting_del_edge = 0;
		}

		if(sigalrm) {
			avl_node_t *node;
			logger(LOG_INFO, "Flushing event queue");
			expire_events();
			for(node = connection_tree->head; node; node = node->next) {
				connection_t *c = node->data;
				if(c->status.active)
					send_ping(c);
			}
			sigalrm = false;
		}

		while((event = get_expired_event())) {
			event->handler(event->data);
			free_event(event);
		}

		if(sighup) {
			connection_t *c;
			avl_node_t *node, *next;
			char *fname;
			struct stat s;
			
			sighup = false;

			reopenlogger();
			
			/* Reread our own configuration file */

			exit_configuration(&config_tree);
			init_configuration(&config_tree);

			if(!read_server_config()) {
				logger(LOG_ERR, "Unable to reread configuration file, exitting.");
				return 1;
			}

			/* Cancel non-active outgoing connections */

			for(node = connection_tree->head; node; node = next) {
				next = node->next;
				c = node->data;

				c->outgoing = NULL;

				if(c->status.connecting) {
					terminate_connection(c, false);
					connection_del(c);
				}
			}

			/* Wipe list of outgoing connections */

			for(list_node_t *node = outgoing_list->head; node; node = node->next) {
				outgoing_t *outgoing = node->data;

				if(outgoing->event)
					event_del(outgoing->event);
			}

			list_delete_list(outgoing_list);

			/* Close connections to hosts that have a changed or deleted host config file */
			
			for(node = connection_tree->head; node; node = node->next) {
				c = node->data;
				
				xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
				if(stat(fname, &s) || s.st_mtime > last_config_check)
					terminate_connection(c, c->status.active);
				free(fname);
			}

			last_config_check = now;

			/* If StrictSubnet is set, expire deleted Subnets and read new ones in */

			if(strictsubnets) {
				subnet_t *subnet;

				for(node = subnet_tree->head; node; node = node->next) {
					subnet = node->data;
					subnet->expires = 1;
				}

				load_all_subnets();

				for(node = subnet_tree->head; node; node = next) {
					next = node->next;
					subnet = node->data;
					if(subnet->expires == 1) {
						send_del_subnet(everyone, subnet);
						if(subnet->owner->status.reachable)
							subnet_update(subnet->owner, subnet, false);
						subnet_del(subnet->owner, subnet);
					} else if(subnet->expires == -1) {
						subnet->expires = 0;
					} else {
						send_add_subnet(everyone, subnet);
						if(subnet->owner->status.reachable)
							subnet_update(subnet->owner, subnet, true);
					}
				}
			}

			/* Try to make outgoing connections */
			
			try_outgoing_connections();
		}
		
		/* Dump graph if wanted every 60 seconds*/

		if(last_graph_dump + 60 <= now) {
			dump_graph();
			last_graph_dump = now;
		}
	}

#ifdef HAVE_PSELECT
	/* Restore SIGHUP & SIGALARM mask */
	sigprocmask(SIG_SETMASK, &omask, NULL);
#endif

	return 0;
}
Пример #30
0
bool ack_h(connection_t *c, const char *request) {
	if(c->protocol_minor == 1)
		return upgrade_h(c, request);

	char hisport[MAX_STRING_SIZE];
	char *hisaddress;
	int weight, mtu;
	uint32_t options;
	node_t *n;
	bool choice;

	if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
			   c->hostname);
		return false;
	}

	/* Check if we already have a node_t for him */

	n = lookup_node(c->name);

	if(!n) {
		n = new_node();
		n->name = xstrdup(c->name);
		node_add(n);
	} else {
		if(n->connection) {
			/* Oh dear, we already have a connection to this node. */
			logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Established a second connection with %s (%s), closing old connection", n->connection->name, n->connection->hostname);

			if(n->connection->outgoing) {
				if(c->outgoing)
					logger(DEBUG_ALWAYS, LOG_WARNING, "Two outgoing connections to the same node!");
				else
					c->outgoing = n->connection->outgoing;

				n->connection->outgoing = NULL;
			}

			terminate_connection(n->connection, false);
			/* Run graph algorithm to purge key and make sure up/down scripts are rerun with new IP addresses and stuff */
			graph();
		}
	}

	n->connection = c;
	c->node = n;
	if(!(c->options & options & OPTION_PMTU_DISCOVERY)) {
		c->options &= ~OPTION_PMTU_DISCOVERY;
		options &= ~OPTION_PMTU_DISCOVERY;
	}
	c->options |= options;

	if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu)
		n->mtu = mtu;

	if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu)
		n->mtu = mtu;

	if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) {
		if(choice)
			c->options |= OPTION_CLAMP_MSS;
		else
			c->options &= ~OPTION_CLAMP_MSS;
	}

	/* Activate this connection */

	c->allow_request = ALL;

	logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection with %s (%s) activated", c->name,
			   c->hostname);

	/* Send him everything we know */

	send_everything(c);

	/* Create an edge_t for this connection */

	c->edge = new_edge();
	c->edge->from = myself;
	c->edge->to = n;
	sockaddr2str(&c->address, &hisaddress, NULL);
	c->edge->address = str2sockaddr(hisaddress, hisport);
	free(hisaddress);
	sockaddr_t local_sa;
	socklen_t local_salen = sizeof local_sa;
	if (getsockname(c->socket, &local_sa.sa, &local_salen) < 0)
		logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get local socket address for connection with %s", c->name);
	else {
		char *local_address;
		sockaddr2str(&local_sa, &local_address, NULL);
		c->edge->local_address = str2sockaddr(local_address, myport);
		free(local_address);
	}
	c->edge->weight = (weight + c->estimated_weight) / 2;
	c->edge->connection = c;
	c->edge->options = c->options;

	edge_add(c->edge);

	/* Notify everyone of the new edge */

	if(tunnelserver)
		send_add_edge(c, c->edge);
	else
		send_add_edge(everyone, c->edge);

	/* Run MST and SSSP algorithms */

	graph();

	return true;
}