Go Down

Topic: Ethernet server with client´s IP address filter (Read 2004 times) previous topic - next topic

Slavo

Hello evereyone,

I´m using arduino with the ethernet shield and arduino webserver example. In this example, arduino reads client´s get requests and respond with some html page. My problem is, that I want to respond only for one defined client. In header of every packet of client´s get request is his source IP address. So, i would like to read this IP, compare with pre the predefined and if there is a match, then send the response...but i can´t find some function in the ethernet library to access packet header or specifically its source IP address. Is there someone, who knows, how to do this stuff ? Is there any additional library to work with packets ?

Every suggestion is welcomed. 

SurferTim

#1
Dec 01, 2012, 04:36 pm Last Edit: Dec 01, 2012, 06:20 pm by SurferTim Reason: 1
I modified the IDE v1.0.2 ethernet library to retrieve the client ip. I attached the modified files to this post.
Ethernet.h
Ethernet.cpp
EthernetClient.h
EthernetClient.cpp

Save your original library files first! Then replace with these.

To get the client ip in your sketch:
Code: [Select]
 EthernetClient client = server.available();
 if(client) {
   Serial.print("Client IP: ");
   Serial.println(client.remoteIP());
 // rest of your loop code


edit: I put the comment "// SurferTim added" at each change in the files if you want to know what was changed.

If you want to restrict your remote IP to the 192.168.1.x subnet, this works:
Code: [Select]
    IPAddress ipBuf;   
    Serial.print("Client IP: ");
    ipBuf = client.remoteIP();
    Serial.println(ipBuf);

    if((ipBuf[0] == 192) && (ipBuf[1] == 168) && (ipBuf[2] == 1)) Serial.println("IP OK");
    else Serial.println("IP fail");
   

zoomkat

Probably a similar way to get the remote IP in the discussion below.

http://arduino.cc/forum/index.php/topic,82416.msg619420.html#msg619420

Code: [Select]

//zoomkat 12-8-11
//simple button GET with iframe code
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields

#include <SPI.h>
#include <Ethernet.h>

byte rip[4];
//byte rip[] = {0,0,0,0};
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

String readString;

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();

  //enable serial data print
  Serial.begin(9600);
  Serial.println("server LED test 1.0"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string
          readString += c;
          //Serial.print(c);
        }

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging
client.getRemoteIP(rip);
for (int bcount= 0; bcount < 4; bcount++)
     {
        Serial.print(rip[bcount], DEC);
        if (bcount<3) Serial.print(".");
     }

Serial.println();
          //now output HTML data header
             if(readString.indexOf('?') >=0) { //don't send new page
               client.println("HTTP/1.1 204 Zoomkat");
               client.println();
               client.println(); 
             }
             else {
          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();

          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Arduino GET test page</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          client.println("<H1>Zoomkat's simple Arduino button</H1>");
         
          client.println("<a href=\"/?on\" target=\"inlineframe\">ON</a>");
          client.println("<a href=\"/?off\" target=\"inlineframe\">OFF</a>");

          //client.println("<IFRAME name=inlineframe src=\"res://D:/WINDOWS/dnserror.htm\" width=1 height=1\">");
          client.println("<IFRAME name=inlineframe style=\"display:none\" >");         
          client.println("</IFRAME>");

          client.println("</BODY>");
          client.println("</HTML>");
             }

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on") >0)//checks for on
          {
            digitalWrite(5, HIGH);    // set pin 5 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(5, LOW);    // set pin 5 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
}

Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

SurferTim

@zoomkat: It probably does if the ethernet library has been modified to include this function. This is not a function in the standard ethernet library.
Code: [Select]
client.getRemoteIP(rip);
There is really one way to get the remote IP in the W5100 code. All roads lead to Rome, so to speak.

Slavo

Thank you very much, it works as I wanted ... :)

zoomkat


@zoomkat: It probably does if the ethernet library has been modified to include this function. This is not a function in the standard ethernet library.
Code: [Select]
client.getRemoteIP(rip);
There is really one way to get the remote IP in the W5100 code. All roads lead to Rome, so to speak.



it is interesting that the "rip" way I used only required two file mods and your way used four. Maybe the "ethernet" files actually call the "ethernetclient" files during the compile process. My code calls ethernet.h but I modified the ethernetclient files (and things seem to work).  I'm sure it all goes back to the programming of the w5100 chips and what is available there for use.
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

SurferTim

#6
Dec 01, 2012, 07:42 pm Last Edit: Dec 01, 2012, 07:57 pm by SurferTim Reason: 1
@zoomkat: That was the first challenge. The IPAddress stuff is in Ethernet.h and Ethernet.cpp, and the socket number is in EthernetClient.h and EthernetClient.cpp. I make an intermediate call to the EthernetClient module to get the current socket number. I use the Ethernet module to be able to return an IPAddress type. Just a matter of convenience, I guess. It stays in convention with the other ip address functions.

For those who haven't figured out what this does, it is a miniature firewall.

Seky

Hello.. I see this is old topic but I have a problem using this modifications to libraryes.. When I have download your modified files and put them in my src folder of ethernet library it says:


Proba_server.ino: In function 'void loop()':
Proba_server:76: error: 'class EthernetClient' has no member named 'remoteIP'

I tried changing few diffrent things in librarys that i have seen on forum but nothing helps

SurferTim

If you got that message, you did not successfully replace the files. Did you download and replace all four files in libraries/Ethernet? All these:
EthernetClient.h
EthernetClient.cpp
Ethernet.h
Ethernet.cpp


I always recommend renaming the originals so you have something to go back to if all else fails.

Seky

Thanks for quick reply,
I didn't bother of making backups because you nicely marked what you changed.
And I did replaced all 4 files. 2 or 3 times to be sure. Thats why I do not understand bug. I use 1.0.6 version of software and arduino uno

SurferTim

Are you certain you replaced the correct files? Are you using Windows? They may be in c:/Program files/Arduino.


Seky

I feel little stupid now. I don't know why but I had ethernet library in My Documents\Arduino. When I replaced ones in C:\Program Files it started to work. And I explicitly imported the replaced libraryes from My Documents so I do not understand now. But it is importat that it works now

Thank you  :D

Seky

I'm reading trough ethernet and ethernetclient libraryes and I can't find some function that can return socket number of curent client that I'm printing IP of. I don't know how to add that to library file.
If i understood it right socket number is something like a channel on which server and client communicates and I have a need to see that channel. If there is a way to see it I would be grateful

SurferTim

#13
Mar 09, 2015, 01:23 pm Last Edit: Mar 09, 2015, 01:24 pm by SurferTim
I haven't tried it, but this should do it for you.

Add this in EthernetClient.h after the status function prototype
Code: [Select]
  uint8_t status();

// add this
  uint8_t getSocket();



Add this to EthernetClient.cpp after my remoteIP function
Code: [Select]
// SurferTim added
IPAddress EthernetClient::remoteIP() {
    return Ethernet.remoteIP(_sock);
}
// end of add

// add this
uint8_t EthernetClient::getSocket() {
  return(_sock);
}


Then use it like this:
Code: [Select]
byte thisSocket = client.getSocket();
It will return the socket numbers 0 to 3 (or 0 to 7 if w5200) or MAX_SOCK_NUM, which is 4 (or 8 if w5200) if no socket number.

Seky

The result is as expected. I use 2 clients in local network. But every time i make a request to server client get diffrent socket. They're jumping from 0 to 1. Sometimes 2. I thought that when they connect they will have static socket just for that client until it dissconets

Take a look at code. This does nothing smart but I'm trying to implement some light security for home automation

The index page have Text box and submit button. Page 2 only have one paragraph which says you are logged in

I want for multiple user to be able to connect and each have to insert password and then then they can change some stuff on page 2. I welcome every idea and suggestion.. In meantime i will try some more stuff

Code: [Select]
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

#define REQ_BUF_SZ   40

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = {
  192, 168, 0, 102 }; // ip in lan
byte gateway[] = {
  192, 168, 0, 1 }; // internet access via router
byte subnet[] = {
  255, 255, 255, 0 }; //subnet mask
EthernetServer server(80);
; //server port
File webFile;                    // handle to files on SD card
char HTTP_req[REQ_BUF_SZ] = {
  0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer
boolean sifra_ok=0;
boolean sifra[4]={0};
byte ip_klijennt[4]={0};


//////////////////////

void setup(){
  // disable Ethernet chip
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
 Serial.begin(9600);
  // initialize SD card
  Serial.println("Initializing SD card...");
  if (!SD.begin(4)) {
    Serial.println("ERROR - SD card initialization failed!");
    return;    // init failed
  }
  Serial.println("SUCCESS - SD card initialized.");
  // check for index.htm file
  if (!SD.exists("index.htm")) {
    Serial.println("ERROR - Can't find index.htm file!");
    return;  // can't find index file
  }
  Serial.println("SUCCESS - Found index.htm file.");
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();

  //enable serial data print
 
  Serial.println("Pass test"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();

  if (client) {
      Serial.print("Client IP: ");
   Serial.println(client.remoteIP());
   Serial.print("Socket je:");
   byte thisSocket = client.getSocket();
   Serial.println(thisSocket);
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        if (req_index < (REQ_BUF_SZ - 1)) {
          HTTP_req[req_index] = c;          // save HTTP request character
          req_index++;
        }

Serial.print(c);
        //if HTTP request has ended
        if (c == '\n' && currentLineIsBlank) {
         Serial.println();
         Serial.println(HTTP_req);

           //see what was captured
if(StrContains(HTTP_req, "Pass=sifra"))
{
sifra_ok=1;}
else if(StrContains(HTTP_req, "Pass=") || StrContains(HTTP_req, "GET / ")  || StrContains(HTTP_req, "GET /index.htm"))
{sifra_ok=0;
webFile = SD.open("index.htm");}
          //now output HTML data header

          client.println(F("HTTP/1.1 200 OK"));
          client.println(F("Content-Type: text/html"));
          client.println(F("Connnection: close"));
          client.println();



          if (sifra_ok) {
            webFile = SD.open("page2.htm");        // open web page file
          }
          else if (StrContains(HTTP_req, "GET / ")  || StrContains(HTTP_req, "GET /index.htm")) {
            webFile = SD.open("index.htm");        // open web page file
          }
          // send web page to client
          if (webFile) {
            while(webFile.available()) {
              client.write(webFile.read());
            }
            webFile.close();
          }
          // reset buffer index and all buffer elements to 0
          req_index = 0;
          StrClear(HTTP_req, REQ_BUF_SZ);
          break;
        }
        // every line of text received from the client ends with \r\n
        if (c == '\n') {
          // last character on line of received text
          // starting new line with next character read
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // a text character was received from client
          currentLineIsBlank = false;
        }
      } // end if (client.available())
    } // end while (client.connected())
    delay(1);      // give the web browser time to receive the data
    client.stop(); // close the connection
  } // end if (client)
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
  for (int i = 0; i < length; i++) {
    str[i] = 0;
  }
}

// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
  char found = 0;
  char index = 0;
  char len;

  len = strlen(str);

  if (strlen(sfind) > len) {
    return 0;
  }
  while (index < len) {
    if (str[index] == sfind[found]) {
      found++;
      if (strlen(sfind) == found) {
        return 1;
      }
    }
    else {
      found = 0;
    }
    index++;
  }

  return 0;
}

Go Up