#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <netinet/in.h>

#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/ax25.h>
#include <linux/netrom.h>

#include "config.h"
#include "netromd.h"

void receive_nodes(unsigned char *buffer, int length, ax25_address *neighbour, int index)
{
	struct nr_route_struct nr_node;
	struct nr_parms_struct nr_parms;
	char neigh_buffer[90], *p;
	FILE *fp;
	int s, i;
	int quality;
	char *callsign, *device;

	nr_node.type = NETROM_NODE;

	if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
		perror("NET/ROM socket");
		exit(1);
	}

	if ((fp = fopen(NEIGH_FILE, "r")) == NULL) {
		fprintf(stderr, "error: cannot open %s\n", NEIGH_FILE);
		exit(1);
	}
	
	if (ioctl(s, SIOCNRGETPARMS, &nr_parms) == -1) {
		perror("get parms");
		exit(1);
	}

	p = ax2asc(neighbour);

	quality = port_list[index].default_qual;

	while (fgets(neigh_buffer, 90, fp) != NULL) {
		strtok(neigh_buffer, " ");
		callsign = strtok(NULL, " ");
		device   = strtok(NULL, " ");

		if (strcmp(callsign, p) == 0 && strcmp(device, port_list[index].device) == 0) {
			quality = atoi(strtok(NULL, " "));
			break;
		}
	}

	nr_node.callsign    = *neighbour;
	memcpy(nr_node.mnemonic, buffer, 6);
	for (i = 0; i < 6; i++) {
		if (nr_node.mnemonic[i] == ' ') {
			nr_node.mnemonic[i] = '\0';
			break;
		}
	}
	nr_node.mnemonic[6] = '\0';
	nr_node.neighbour   = *neighbour;
	strcpy(nr_node.device, port_list[index].device);
	nr_node.quality     = quality;
	nr_node.obs_count   = nr_parms.obs_count;

	if (ioctl(s, SIOCADDRT, &nr_node) == -1) {
		perror("add route");
		exit(1);
	}

	buffer += 6;
	length -= 6;

	while (length > 0) {
		if (ax25cmp(&my_call, (ax25_address *)(buffer + 13)) != 0 &&
		    buffer[20] > port_list[index].worst_qual) {
			memcpy(&nr_node.callsign, buffer + 0, 7);
			memcpy(nr_node.mnemonic, buffer + 7, 6);
			for (i = 0; i < 6; i++) {
				if (nr_node.mnemonic[i] == ' ') {
					nr_node.mnemonic[i] = '\0';
					break;
				}
			}
			nr_node.mnemonic[6] = '\0';
			nr_node.neighbour   = *neighbour;
			strcpy(nr_node.device, port_list[index].device);
			nr_node.quality     = ((quality * buffer[20]) + 128) / 256;
			nr_node.obs_count   = nr_parms.obs_count;

			if (ioctl(s, SIOCADDRT, &nr_node) == -1) {
				perror("add route");
				exit(1);
			}
		}

		buffer += 21;
		length -= 21;
	}

	fclose(fp);
	close(s);
}
