/*
 * IS THREADSAFE
 */
int add_local_ip_filter(router_state* rs, struct in_addr* ip, char* name) {
	if (get_local_ip_filter_by_ip(rs, ip) || get_local_ip_filter_by_name(rs, name)) {
		return 1;
	}

	node* cur = node_create();
	local_ip_filter_entry* entry = (local_ip_filter_entry*)calloc(1, sizeof(local_ip_filter_entry));
	strncpy(entry->name, name, (LOCAL_IP_FILTER_ENTRY_NAME_LEN - 1));
	entry->ip.s_addr = ip->s_addr;
	cur->data = entry;

	lock_local_ip_filters(rs);

	if (!rs->local_ip_filter_list) {
		rs->local_ip_filter_list = cur;
	} else {
		node_push_back(rs->local_ip_filter_list, cur);
	}

	unlock_local_ip_filters(rs);

	trigger_local_ip_filters_change(rs);

	return 0;
}
Beispiel #2
0
void register_cli_command(node** head, char* command, cli_command_handler handler) {
	node* n = node_create();
	n->data = create_cli_entry(command, handler);

	if (!(*head)) {
		(*head) = n;
	} else {
		node_push_back(*head, n);
	}
}
Beispiel #3
0
/*初始化路由器列表,包括每个路由器的编号、距离之类的(搭拓扑的时候可能要用)*/
void init_router_list(struct sr_instance* sr){

	assert(sr);
	router_state *rs = get_router_state(sr);

	/* build an entry for our router */
	pwospf_router *our_router = (pwospf_router *)calloc(1, sizeof(pwospf_router));
	our_router->router_id = rs->router_id;
	our_router->area_id = rs->area_id;
	our_router->seq = 0;
	our_router->distance = 0;
	our_router->shortest_path_found = 0;
	time(&our_router->last_update);


	/* insert our_router in the pwospf router list */
	assert(rs->pwospf_router_list == NULL);
	node *n = node_create();
	n->data = (void *)our_router;
	rs->pwospf_router_list = n;


	/* advertise what's directly connected to us */
	node *il_walker = rs->if_list;
	while(il_walker) {
		iface_entry *ie = (iface_entry *)il_walker->data;

		pwospf_interface *pi = (pwospf_interface *)calloc(1, sizeof(pwospf_interface));
		pi->subnet.s_addr = (ie->ip & ie->mask);
		pi->mask.s_addr = ie->mask;
		pi->router_id = 0;
		pi->is_active = 0;

		node *rl_entry = node_create();
		rl_entry->data = (void *)pi;
		if(our_router->interface_list == NULL) {
			our_router->interface_list = rl_entry;
		}
		else {
			node_push_back(our_router->interface_list, rl_entry);
		}

		il_walker = il_walker->next;
	}


	//char *str; int len;
	//sprint_pwospf_router_list(rs, &str, &len);
	//printf("\nINITIAL ROUTER LIST:\n\n%s\n\n", str);
}
Beispiel #4
0
/*
 * NOT THREAD SAFE, LOCK THE ARP CACHE
 * Return: 0 on success, 1 on failure
 */
int update_arp_cache(struct sr_instance* sr, struct in_addr* remote_ip, char* remote_mac, int is_static) {
	assert(sr);
	assert(remote_ip);
	assert(remote_mac);

	router_state *rs = (router_state *)sr->interface_subsystem;
	arp_cache_entry *arp_entry = 0;

	arp_entry = in_arp_cache(rs, remote_ip);
	if(arp_entry) {

		/* if this remote ip is in the cache, update its data */
		memcpy(arp_entry->arp_ha, remote_mac, ETH_ADDR_LEN);
		if (is_static == 1) {
			arp_entry->TTL = 0;
		} else {
			time(&arp_entry->TTL);
		}
		arp_entry->is_static = is_static;

	}	else {

		/* if this interface is not in the cache, create a new entry */
		node* n = node_create();
		arp_entry = calloc(1, sizeof(arp_cache_entry));

		arp_entry->ip.s_addr = remote_ip->s_addr;
		memcpy(arp_entry->arp_ha, remote_mac, ETH_ADDR_LEN);
		if (is_static == 1) {
			arp_entry->TTL = 0;
		} else {
			time(&arp_entry->TTL);
		}
		arp_entry->is_static = is_static;

		n->data = (void *)arp_entry;
		if(rs->arp_cache == NULL) {
			rs->arp_cache = n;
		} else {
			node_push_back(rs->arp_cache, n);
		}

	}

	/* update the hw arp cache copy */
	trigger_arp_cache_modified(rs);

	return 0;
}
Beispiel #5
0
/*
 * Helper function for arp_queue_add, not to be called externally
 */
void arp_queue_entry_add_packet(arp_queue_entry* aqe, uint8_t* packet, unsigned int len) {
	node* n = node_create();
	arp_queue_packet_entry* aqpe = (arp_queue_packet_entry*)malloc(sizeof(arp_queue_packet_entry));

	aqpe->packet = packet;
	aqpe->len = len;
	/* set the new nodes data to point to the packet entry */
	n->data = aqpe;
	/* add the new node to the arp queue entry */
	if (aqe->head == NULL) {
		aqe->head = n;
	} else {
		node_push_back(aqe->head, n);
	}
}
Beispiel #6
0
void arp_queue_add(struct sr_instance* sr, uint8_t* packet, unsigned int len, const char* out_iface_name, struct in_addr *next_hop)
{
	assert(sr);
	assert(packet);
	assert(out_iface_name);
	assert(next_hop);

	router_state *rs = get_router_state(sr);

	/* Is there an existing queue entry for this IP? */
	arp_queue_entry* aqe = get_from_arp_queue(sr, next_hop);
	if (!aqe) {
		/* create a new queue entry */
		aqe = (arp_queue_entry*)malloc(sizeof(arp_queue_entry));
		bzero(aqe, sizeof(arp_queue_entry));
		memcpy(aqe->out_iface_name, out_iface_name, IF_LEN);
		aqe->next_hop = *next_hop;

		/* send a request */
		time(&(aqe->last_req_time));
		aqe->requests = 1;
		send_arp_request(sr, next_hop->s_addr, out_iface_name);

		arp_queue_entry_add_packet(aqe, packet, len);

		/* create a node, add this entry to the node, and push it into our linked list */
		node* n = node_create();
		n->data = aqe;

		if (rs->arp_queue == NULL) {
			rs->arp_queue = n;
		} else {
			node_push_back(rs->arp_queue, n);
		}
	} else {
		/* entry exists, just add the packet */
		arp_queue_entry_add_packet(aqe, packet, len);
	}
}
Beispiel #7
0
/* --- CCDN 初始化路由表,将来可以参照
功能:从sr的rtable字段读取名字,在当前工作目录下找到相应的文件,
从文件中读取路由表entry,然后将每条entry加入到table里面*/
void init_rtable(struct sr_instance* sr) {
	/* get the rtable lock */
	lock_rtable_wr(get_router_state(sr));

	/* the sr_instance only holds 32 chars of the path to the rtable file so we have
	 * to pass it in as a relative path to the working directory, which requires
	 * us to get the working directory, do some string manipulation, and append
	 * the relative path to the end of the working directory */
	char path[256];
	bzero(path, 256);
	getcwd(path, 256);//获取当前工作的绝对路径,存到path中
	int len = strlen(path);
	path[len] = '/';
	strcpy(path+len+1, sr->rtable);
	FILE* file = fopen(path, "r");
  if (file == NULL) {
  	perror("Failure opening file");
   	exit(1);
  }
  /* 前面这一大块干的是就是在工作目录下找到一个文件(例如rtable),里面存路由表之类的信息 */

  char buf[1024];
  bzero(buf, 1024);

  router_state* rs = (router_state*)sr->interface_subsystem;

  /* walk through the file one line at a time adding its contents to the rtable */
  /* 下面这个while干的事情是从文件中读取ip表,然后把它们加入到rtable里面 */
  while (fgets(buf, 1024, file) != NULL) {
  	char* ip = NULL;
  	char* gw = NULL;
  	char* mask = NULL;
  	char* iface = NULL;
  	if (sscanf(buf, "%as %as %as %as", &ip, &gw, &mask, &iface) != 4) {
  		printf("Failure reading from rtable file\n");
  	}

  	rtable_entry* entry = (rtable_entry*)malloc(sizeof(rtable_entry));
  	bzero(entry, sizeof(rtable_entry)); // bzero,清空整个地址空间

  	if (inet_pton(AF_INET, ip, &(entry->ip)) == 0) {//点分十进制->整数之间的转换,AF_INET指地址簇,可以理解为IPv4
  		perror("Failure reading rtable");  // perror:标准错误流,会讲错误的原因输出到屏幕上。
  	}
  	if (inet_pton(AF_INET, gw, &(entry->gw)) == 0) {
  		perror("Failure reading rtable");
  	}
  	if (inet_pton(AF_INET, mask, &(entry->mask)) == 0) {
  		perror("Failure reading rtable");
  	}
  	strncpy(entry->iface, iface, 32);

  	entry->is_active = 1;
  	entry->is_static = 1;
  	/* create a node, set data pointer to the new entry */
  	node* n = node_create();
  	n->data = entry;

  	if (rs->rtable == NULL) {
  		rs->rtable = n;
  	} else {
  		node_push_back(rs->rtable, n);
  	}


  	char ip_array[INET_ADDRSTRLEN];
  	char gw_array[INET_ADDRSTRLEN];
  	char mask_array[INET_ADDRSTRLEN];

  	printf("Read: %s ", inet_ntop(AF_INET, &(entry->ip), ip_array, INET_ADDRSTRLEN));
  	printf("%s ", inet_ntop(AF_INET, &(entry->gw), gw_array, INET_ADDRSTRLEN));
  	printf("%s ", inet_ntop(AF_INET, &(entry->mask), mask_array, INET_ADDRSTRLEN));
  	printf("%s\n", entry->iface);
  }


	if (fclose(file) != 0) {
		perror("Failure closing file");
	}

	/* check if we have a default route entry, if so we need to add it to our pwospf router */
	pwospf_interface* default_route = default_route_present(rs);

	/* release the rtable lock */
	unlock_rtable(get_router_state(sr));

	if (default_route) {
		lock_mutex_pwospf_router_list(rs);

		pwospf_router* r = get_router_by_rid(rs->router_id, rs->pwospf_router_list);
		node* n = node_create();
		n->data = default_route;

		if (r->interface_list) {
			node_push_back(r->interface_list, n);
		} else {
			r->interface_list = n;
		}

		unlock_mutex_pwospf_router_list(rs);
	}
	/* tell our dijkstra algorithm to run */
	dijkstra_trigger(rs);
	printf("init_rtable finish \n");
}
Beispiel #8
0
/*init_add_interface功能:初始化了4个网口的mac地址等信息*/
void init_add_interface(struct sr_instance* sr, struct sr_vns_if* vns_if) {
	/* do not add any of the cpu interfaces */
	if (strstr(vns_if->name, "cpu")) {//函数功能是查name里面是否有cpu这个字符串,没有返回NULL
		return;
	}

	router_state* rs = (router_state*)sr->interface_subsystem;
	node* n = node_create();

	iface_entry* ie = (iface_entry*)malloc(sizeof(iface_entry));
	bzero(ie, sizeof(iface_entry));
	ie->is_active = 1;
	ie->ip = vns_if->ip;
	ie->mask = vns_if->mask;
	ie->speed = vns_if->speed;
	ie->is_wan = 0;
	memcpy(ie->addr, vns_if->addr, ETH_ADDR_LEN);
	memcpy(ie->name, vns_if->name, IF_LEN);
//	ie->hello_interval = PWOSPF_NEIGHBOR_TIMEOUT;


	/* router id is the same as the ip of the 0th iface */
	if(strncmp(ie->name, "eth0", IF_LEN) == 0) {
		rs->router_id = ie->ip;
	}

	n->data = ie;

	if (rs->if_list == NULL) {
		rs->if_list = n;
	} else {
		node_push_back(rs->if_list, n);
	}

	if (rs->is_netfpga) {
		/* set this on hardware */
		unsigned int mac_hi = 0;
		mac_hi |= ((unsigned int)vns_if->addr[0]) << 8;
		mac_hi |= ((unsigned int)vns_if->addr[1]);
		unsigned int mac_lo = 0;
		mac_lo |= ((unsigned int)vns_if->addr[2]) << 24;
		mac_lo |= ((unsigned int)vns_if->addr[3]) << 16;
		mac_lo |= ((unsigned int)vns_if->addr[4]) << 8;
		mac_lo |= ((unsigned int)vns_if->addr[5]);

		switch (getPortNumber(vns_if->name)) {
			case 0:
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_0_HI_REG, mac_hi);
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_0_LO_REG, mac_lo);
				break;
			case 1:
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_1_HI_REG, mac_hi);
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_1_LO_REG, mac_lo);
				break;
			case 2:
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_2_HI_REG, mac_hi);
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_2_LO_REG, mac_lo);
				break;
			case 3:
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_3_HI_REG, mac_hi);
				writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_3_LO_REG, mac_lo);
				break;
		}
	}

	/* add a local ip filter as well */
	struct in_addr ip;
	ip.s_addr = vns_if->ip;
	add_local_ip_filter(rs, &ip, vns_if->name);
}
Beispiel #9
0
int main(int argc, char** argv)
{
	int our_rid = atoi(argv[1]);

	FILE* file = fopen(argv[2], "r");
  if (file == NULL) {
  	perror("Failure opening file");
   	exit(1);
  }

  char* buf = (char*)malloc(1024);
  bzero(buf, 1024);

  node* iface_list = NULL;
  node* router_list = NULL;
  unsigned char is_iface_line = 1;
	unsigned char is_router_line = 0;
	unsigned char is_interface_line = 0;
	pwospf_router* cur_router = NULL;

  while (fgets(buf, 1024, file) != NULL) {
  	if (buf[0] == '#') {
  		continue;
  	}

		if (is_iface_line) {
			iface_entry* iface = (iface_entry*)calloc(1, sizeof(iface_entry));
			char* ip_str = NULL;
			//char* nbr_ip_str = NULL;
			char* mask_str = NULL;

			/* FIXME
			if (sscanf(buf, "%15s %as %as %as %u", iface->name, &ip_str, &nbr_ip_str, &mask_str, &(iface->nbr_router_id)) != 5) {
				free(iface);
				cur_router = NULL;
				is_iface_line = 0;
				is_router_line = 1;
				continue;
	  	}
			*/

	  	if (inet_pton(AF_INET, ip_str, &(iface->ip)) == 0) {
	  		perror("Failure reading ip");
	  	}

			/* FIXME
	  	if (inet_pton(AF_INET, nbr_ip_str, &(iface->nbr_ip)) == 0) {
	  		perror("Failure reading nbr_ip");
	  	}
	  	*/

	  	if (inet_pton(AF_INET, mask_str, &(iface->mask)) == 0) {
	  		perror("Failure reading mask");
	  	}

			iface->is_active = 1;

			node* n = node_create();
			n->data = iface;
			if (!(iface_list)) {
				iface_list = n;
			} else {
				node_push_back(iface_list, n);
			}
		} else if (is_router_line) {
			cur_router = (pwospf_router*)calloc(1, sizeof(pwospf_router));
			unsigned int seq_temp;
	  	if (sscanf(buf, "%u %u %u", &(cur_router->router_id), &(cur_router->area_id), &(seq_temp)) != 3) {
	  		printf("Failure reading from rtable file\n");
	  	}
	  	cur_router->seq = seq_temp;

			/* add it to the list */
			node* n = node_create();
			n->data = cur_router;
			if (!router_list) {
				router_list = n;
			} else {
				node_push_back(router_list, n);
			}

			is_router_line = 0;
			is_interface_line = 1;
		} else if (is_interface_line) {
			pwospf_interface* iface = (pwospf_interface*)calloc(1, sizeof(pwospf_interface));
			char* subnet_str = NULL;
			char* mask_str = NULL;

			if (sscanf(buf, "%as %as %u", &subnet_str, &mask_str, &(iface->router_id)) != 3) {
				free(iface);
				cur_router = NULL;
				is_interface_line = 0;
				is_router_line = 1;
				continue;
	  	}

			iface->is_active = 1;

	  	if (inet_pton(AF_INET, subnet_str, &(iface->subnet)) == 0) {
	  		perror("Failure reading subnet");
	  	}
	  	if (inet_pton(AF_INET, mask_str, &(iface->mask)) == 0) {
	  		perror("Failure reading mask");
	  	}

			node* n = node_create();
			n->data = iface;
			/* add it to the current router */
			if (!(cur_router->interface_list)) {
				cur_router->interface_list = n;
			} else {
				node_push_back(cur_router->interface_list, n);
			}
		}

  }

	if (fclose(file) != 0) {
		perror("Failure closing file");
	}

	print_pwospf_router_list(router_list);

	node* rtable = compute_rtable(our_rid, router_list, iface_list);

	router_state rs;
	rs.rtable = rtable;
	char* rtable_printout;
	int len;
	sprint_rtable(&rs, &rtable_printout, &len);
	printf("%s\n", rtable_printout);
  return 0;
}
Beispiel #10
0
node* compute_rtable(uint32_t our_router_id, node* pwospf_router_list, node* if_list) {
	/* initialize all the entriest to their max distance, except us */
	node* cur = pwospf_router_list;
	pwospf_router* r = NULL;
	pwospf_router* r_shortest = NULL;

	while (cur) {
		r = (pwospf_router*)cur->data;
		if (r->router_id == our_router_id) {
			r->distance = 0;
			r->shortest_path_found = 1;
		} else if (r->router_id != 0) {
			r->distance = 0xFFFFFFFF;
			r->shortest_path_found = 0;
		}

		cur = cur->next;
	}

	/* Set our router as the shortest */
	r_shortest = get_router_by_rid(our_router_id, pwospf_router_list);

	while (r_shortest) {
		/* add this router to N' */
		r_shortest->shortest_path_found = 1;

		/* update the distances to our neighbors */
		update_neighbor_distance(r_shortest, pwospf_router_list);

		/* get the next router with the shortest distance */
		r_shortest = get_shortest(pwospf_router_list);
	}

	/* now have the shortest path to each router, build the temporary route table */
	node* route_wrapper_list = build_route_wrapper_list(our_router_id, pwospf_router_list);
	//print_wrapper_list(route_wrapper_list);

	/* we now have a list of wrapped proper entries, but they need specific interface info,
	 * and need to lose the wrapping
	 */
	node* route_list = NULL;

	cur = route_wrapper_list;
	while (cur) {
		route_wrapper* wrapper = (route_wrapper*)cur->data;
		rtable_entry* new_entry = (rtable_entry*)calloc(1, sizeof(rtable_entry));
		/* just blast the entry information across */
		memcpy(new_entry, &(wrapper->entry), sizeof(rtable_entry));
		/* get the new stuff */
		iface_entry* iface = get_iface_by_rid(wrapper->next_rid, if_list);
		if (!iface) {
			iface = get_iface_by_subnet_mask(&(wrapper->entry.ip), &(wrapper->entry.mask), if_list);
			if (!iface) {
				/* most likely the default entry, assume its static, so just continue */
				free(new_entry);
				cur = cur->next;
				continue;
			}
		}
		assert(iface);

		memcpy(new_entry->iface, iface->name, IF_LEN);

		if (wrapper->directly_connected) {
			new_entry->gw.s_addr = 0;
		} else {
			nbr_router* nbr = get_nbr_by_rid(iface, wrapper->next_rid);
			assert(nbr);
			new_entry->gw.s_addr = nbr->ip.s_addr;
		}

		new_entry->is_active = 1;
		new_entry->is_static = 0;

		/* grab a new node, add it to the list */
		node* temp = node_create();
		temp->data = new_entry;

		if (!route_list) {
			route_list = temp;
		} else {
			node_push_back(route_list, temp);
		}

		cur = cur->next;
	}

	/* run through and free the wrapper list */
	cur = route_wrapper_list;
	while (cur) {
		node* next = cur->next;
		node_remove(&route_wrapper_list, cur);
		cur = next;
	}

	return route_list;
}
Beispiel #11
0
void add_route_wrappers(uint32_t our_rid, node** head, pwospf_router* r) {
	node* cur = r->interface_list;
	while (cur) {
		pwospf_interface* i = (pwospf_interface*)cur->data;

		/* check if we have an existing route matching this subnet and mask */
		node* temp_node = get_route_wrapper(*head, &(i->subnet), &(i->mask));
		if (temp_node) {
			/* if our distance is longer, just continue to the next interface */
			route_wrapper* wrapper = (route_wrapper*)temp_node->data;
			if (r->distance >= wrapper->distance) {
				cur = cur->next;
				continue;
			} else {
				/* replace the existing entries data with ours */
				wrapper->distance = r->distance;
				/* walk down until the next router is the source */
				pwospf_router* cur_router = r;
				if (!cur_router->prev_router) {
					wrapper->next_rid = i->router_id;
				} else {
					while (cur_router->prev_router->distance != 0) {
						cur_router = cur_router->prev_router;
					}

					wrapper->next_rid = cur_router->router_id;
				}

				/* set that this is directly connected to us */
				if (our_rid == r->router_id) {
					wrapper->directly_connected = 1;
				}
			}
		} else {
			node* new_node = node_create();

			/* no existing route wrapper, create a new one for this route */
			route_wrapper* new_route = (route_wrapper*)calloc(1, sizeof(route_wrapper));
			new_route->entry.ip.s_addr = i->subnet.s_addr & i->mask.s_addr;
			new_route->entry.mask.s_addr = i->mask.s_addr;
			new_route->distance = r->distance;

			/* walk down until the next router is the source */
			pwospf_router* cur_router = r;
			if (!cur_router->prev_router) {
				new_route->next_rid = i->router_id;
			} else {
				while (cur_router->prev_router->distance != 0) {
					cur_router = cur_router->prev_router;
				}
				new_route->next_rid = cur_router->router_id;
			}

			/* set that this is directly connected to us */
			if (our_rid == r->router_id) {
				new_route->directly_connected = 1;
			}

			/* point the node's data at our route wrapper */
			new_node->data = new_route;

			if (!(*head)) {
				(*head) = new_node;
			} else {
				node_push_back(*head, new_node);
			}
		}

		cur = cur->next;
	}
}