5.4 NETWORKING IN LINUX
Configuration files are under /etc
Recompile kernel in some cases, such as a firewall. or new hardware
Loadable modules
DHCP versus static IP
Most modern versions of Linux simplify hardware detection and setup. The steps below can help perform the basic operations, or find problems.
A. Installing a normal ethernet network connection:
1. During the installation process you will be asked for network parameters.
2. Enter a unique name for the machine and the network name.
3. (for DHCP) All that should be required is a setting for DHCP.
3. (for a static IP) You will need to enter the static IP number for the machine, as well as a netmask and gateway. If you are connecting to another network you can get these from a network administrator. If you are connecting your own network (not on the Internet) you can simply pick values like those below. Note that you need some sort of network router with an IP address of 192.168.1.254 for this to work.
B. Troubleshooting an ethernet connection to the Internet,
1. Check to see if the network card is recognized with 'more /proc/modules' The card should be in the list. If not the kernel module must be installed.
2. Check to see if the network is setup with ifconfig. You should see 'eth0' or something similar. If it is not setup, the network parameters must be checked.
3. Check to see if the network is connected properly with ping to the local gateway, or another local machine - use the IP number, not the name. For example, 'ping 148.61.104.254'. If this fails the gateway or broadcast addresses are probably incorrect.
4. Check the connection to the outside with a ping such as 'ping 148.61.1.10'. If this is not allowed there is probably a problem with the outside connection
5. Verify that the nameserver is working alright with a ping to a named machine such as, 'ping www.linux.org'.
6. If all of these things work the network connection should be alright.
C. Installing a dialup connection
1. During the installation make sure that the location of your modem is correctly identified. Note: Winmodems are very popular because of their low cost, but there are very few Linux drivers. But... you are advised to spend the money for a non-Winmodem anyway, they are more reliable and they don't use your computers resources.
D. Troubleshooting a dialup connection
1. Use a terminal program to dial the Internet service provider's number manually. If you don't get a response there is a problem with the modem installation.
2. After connected try providing your login ID and password and see if you get in. Expect to see garbage after this. If login is refused you need to check the user ID and password again.
E. Setting up a firewall (this requires some work)
1. To set up a firewall the kernel must be recompiled to include network options such as multicasting, and firewall services.
2. Shut down the computer and add a second network card in the machine and reboot.
3. Check to see if the card is recognized with 'more /proc/modules'. Both ethernet cards should be listed. If not you will need to edit the network startup files. These are normally in '/etc/...' or for slackware '/etc/rc.d'. An example file follows. Reboot and check for both network cards again.
4. Use 'ipchains' to add services to pass, and modify the 'hosts.allow' and 'hosts.deny' files to control access.
[ipchains file declarations]
5.4.1 Network Programming in Linux
The following listings show network usage in Linux. The general method of network connection is different for servers and clients.
For servers.....
For clients....
Listing X.1 - network_io.cpp
network_io::network_io(){
network_io::~network_io(){
} else if (type == _WRITE){
int network_io::set_remote_host(char *_host_name, int host_socket){
unsigned char address[4];
strcpy(host_name, _host_name);
host_socket_number = host_socket;
// Set up server descriptor, get host reference and error trap
write_connection.sin_family = AF_INET;
if((host_name[0] > '9') ||(host_name[0]<'0')){
hp = gethostbyname(host_name);
sscanf(host_name, "%d.%d.%d.%d",
&nm_a, &nm_b, &nm_c, &nm_d);
address[0] = (unsigned char)(nm_a);
address[1] = (unsigned char)(nm_b);
address[2] = (unsigned char)(nm_c);
address[3] = (unsigned char)(nm_d);
hp = gethostbyaddr((char *)address, 4, AF_INET);
/* complete descriptor set up. */
bcopy((char *)hp->h_addr,
(char *)&(write_connection.sin_addr),
error_log(MINOR, "ERROR: unknown network host");
int network_io::set_local_host(int socket_num){
socket_number = socket_num;
int network_io::writer(char *string){
// Open a new socket for the write, and check for errors.
if(error == NO_ERROR) error = open_write_connection();
if(error == NO_ERROR) error = write_to_connection(string);
if(error == NO_ERROR) error = end_write_connection();
if(deinit_write() == ERROR) error = ERROR;
int network_io::reader(char *buf, int length){
static int error; // Error return variable
// Wait for a socket connection request, then get its reference.
if(wait_read_connection() == NO_ERROR){
if(read_from_connection(buf, length) == ERROR){
// Close socket connection to remote write client.
int network_io::init_write(){
struct hostent *gethostbyname();
/* Open a new socket for the write, and check for errors. */
if((rw_socket = socket(AF_INET, SOCK_STREAM, 0)) >= 0){
write_connection.sin_port = htons(host_socket_number);
error_log(MINOR, "ERROR: opening stream socket");
int network_io::open_write_connection(){
if(connect(rw_socket, (struct sockaddr *) &(write_connection), sizeof(write_connection)) < 0){
error_log(MINOR, "ERROR: Connecting stream Socket");
int network_io::write_to_connection(char *text){
if(write(rw_socket, text, strlen(text) /* +1 */) < 0){
error_log(MINOR, "ERROR: writing on stream socket");
int network_io::write_stuff_done(){
int network_io::check_connection(){
ufds.events = POLLOUT | POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
count = poll(&ufds, 1, 0);
if((ufds.revents & 16) != 0) error = ERROR;
int network_io::end_write_connection(){
int network_io::deinit_write(){
int network_io::init_read(){
static int error; // low level socket number
unsigned length; // temporary work variable
static struct sockaddr_in server; // read socket descriptor
static struct hostent *hp;
// Open internet socket, and check for error.
gethostname(text, 100); /* who are we? */
hp = gethostbyname(text);
if((hp != NULL) && (read_socket = socket(AF_INET, SOCK_STREAM, 0)) >= 0){
// Set up server descriptor for binding name.
memset(&server, 0, sizeof(struct sockaddr_in));
server.sin_family = hp->h_addrtype;
server.sin_port = htons(socket_number);
// Bind the socket, and check for error.
setsockopt(read_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(int));
if(bind(read_socket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) >= 0){
// Check for valid socket binding
if(getsockname(read_socket, (struct sockaddr *)&server, &length) >= 0){
// Set up variables for success
// Zero because anything higher would allow
// messages to arrive out of sequence.
error_log(MINOR, "ERROR: getting socket name");
error_log(MINOR, "ERROR: binding stream socket");
error_log(MINOR, "ERROR: opening stream socket");
int network_io::read_stuff_waiting(){
ufds.events = POLLIN | POLLPRI | POLLOUT;
count = poll(&ufds, 1, 0);
if((ufds.revents & 1) > 0){
int network_io::wait_read_connection(){
static struct sockaddr addr;
size = sizeof(struct sockaddr);
fcntl(read_socket, F_SETFL, O_NONBLOCK);
rw_socket = accept(read_socket, &addr, &size);
// error_log("ERROR: warning:accept");
int network_io::read_from_connection(char *buf, int length){
// Read string into buffer from socket
fcntl(rw_socket, F_SETFL, O_NONBLOCK);
len = read(rw_socket, buf, length);
// error_log("ERROR: reading stream message");
printf("errno=%d ", errno);
int network_io::end_read_connection(){
int network_io::deinit_read(){
char *network_io::get_address(){
static char work[MAXIMUM_HOST_NAME_LENGTH];
struct sockaddr_in address;
int_address = address.sin_addr.s_addr;
int_address = gethostid();
addr[i]=int_address & 0xFF;
sprintf(work, "%d.%d.%d.%d",
(int)addr[3], (int)addr[2], (int)addr[1], (int)addr[0]);
sprintf(work, "%d.%d.%d.%d",
(int)addr[0], (int)addr[1], (int)addr[2], (int)addr[3]);
char *network_io::get_remote_client(){
if(getpeername(rw_socket, &address, &len) == 0){
sprintf(work, "%u.%u.%u.%u", address.sa_data[2], address.sa_data[3], address.sa_data[4], address.sa_data[5]);
// printf("Got address [%s]\n", work);
strcpy(work, "unknown network address");
Listing X.2 - network_io.h
#include <linux/socket.h> // sys/socket.h may be needed here
#define ANY 0 // Indicates no socket number prechosen
#define MAXIMUM_HOST_NAME_LENGTH 100
char host_name[MAXIMUM_HOST_NAME_LENGTH];
struct sockaddr_in write_connection;
// char incoming_string[MAXIMUM_STRING_SIZE];
int set_remote_host(char*, int);
int open_write_connection();
int write_to_connection(char*);
// int write_to_read_connection(char*);
int end_write_connection();
int wait_read_connection();
int read_from_connection(char*, int);
// int read_from_write_connection(char*, int);
int end_read_connection();
int read_stuff_waiting();
char* get_remote_client();
Listing X.3 - network.cpp
#include "../network_io/network_io.h"
timeout = 5; // the default timeout
if(network != NULL) delete network;
if(error == NO_ERROR) error = process_command();
if(*state == WAITINGFORCONNECTION){
if(connect_flag == TRUE){
if(network->wait_read_connection() == NO_ERROR){
*state = CONNECTIONESTABLISHED;
sprintf(text, "Got a connection from %s", network->get_remote_client());
error_log(WARNING, text);
} else if(mode == TALKER){
if(network->open_write_connection() == NO_ERROR){
*state = CONNECTIONESTABLISHED;
} else if(*state == CONNECTIONESTABLISHED){
network->write_to_connection(send_buf);
// printf("Sending String [%s]\n", send_buf);
// time(&last_time); // You can keep the connection alive by writing
// but this doesn't guarantee that the remote client is still there
if(*received_flag == FALSE){
if(network->read_from_connection(received_temp, 199) != ERROR){
if(strlen(received_temp) > 0){
strcpy(received, received_temp);
// printf("Got String [%s]\n", received);
if((network->check_connection() == ERROR) || ((mode == LISTENER) && (difftime(now_time, last_time) > timeout))){
network->end_read_connection();
} else if(mode == TALKER){
network->end_write_connection();
*state = WAITINGFORCONNECTION;
if(*change_lock == TRUE){
if(*command == INITIALIZE){
if(*state == NOTINITIALIZED){
network = new network_io();
network->set_local_host(port);
*state = WAITINGFORCONNECTION;
error_log(MINOR, "Parameter did not hold a valid port");
} else if(mode == TALKER){
for(i = 0; i < len; i++){
port = atoi(&(params[i+1]));
if((i < len) && (port > 0)){
network = new network_io();
network->set_remote_host(params, port);
*state = WAITINGFORCONNECTION;
error_log(MINOR, "Address string was not properly formed");
error_log(MINOR, "ERROR: Mode not defined yet");
error_log(MINOR, "Network talker initialize command in wrong state");
} else if(*command == CONNECT){
if(*state == WAITINGFORCONNECTION){
} else if(*command == DISCONNECT){
if(*state == CONNECTIONESTABLISHED){
network->end_write_connection();
} else if (mode == LISTENER){
network->end_read_connection();
*state = WAITINGFORCONNECTION;
error_log(MINOR, "Cannot disconnect network unless connected");
} else if(*command == UNINITIALIZE){
if(*state == WAITINGFORCONNECTION){
} else if (mode == LISTENER){
error_log(MINOR, "Cannot uninitialize network unless waitingforconnection");
} else if(*command == SET){
if(*state == NOTINITIALIZED){
error_log(MINOR, "Can't set network mode after initialization");
} else if(*operand1 == PARAM){
if(*state == NOTINITIALIZED){
if(params != NULL) delete params;
params = new char[strlen(operand3)+1];
strcpy(params, operand3);
error_log(MINOR, "Can't set network parameters, in wrong state");
} else if(*operand1 == TIMEOUT){
error_log(MINOR, "Network SET type not recognized");
error_log(MINOR, "Network command not recognized");
To use the network program as a server the basic flow of control is outlined below,
char temp_in[200]; // an input string
char temp_out[200]; // an output string
// set up the network connection
network_io test = new network_io(); // create a new instance of network
test->set_local_host(1000); // set the program to listen on port 1000
point1: test->init_read(); // start waiting for a client to connect
point2: val = test->wait_read_connection(); // check for a connection
if(val == ERROR) goto point2;
val = test->check_connection();
test->end_read_connection();
// now connected, interact with client
point3: val = test->read_from_connection(temp_in, 199); // get an input string
// do anything needed for the received string
// do anything for writing strings here
if(there is a string to send){
test->write_to_connection(temp_out);
A makefile for the program follows.
$(CC) $(CFLAGS) network.cpp -o network network_io.o
network_io.o: network_io.cpp network_io.h
$(CC) $(CFLAGS) -c network_io.cpp